1 PARTE I – Cuidados antes de começar a rodar os códigos no R

Para que o arquivo fluxo_de_trabalho_codigos_interativo_final.Rmd funcione de maneira adequada em sua mĂĄquina, vocĂȘ deve descompactar o arquivo piper3D_monitora_florestal.zip. Uma nova pasta com o mesmo nome serĂĄ criada no diretĂłrio escolhido para executar a descompactação. Nela, vocĂȘ deverĂĄ clicar duas vezes sobre o Ă­cone Monitora.Rproj para começar a executar os arquivos contidos no projeto. Ao realizar esse procedimento, vocĂȘ garantirĂĄ que seu diretĂłrio de trabalho esteja configurado como o diretĂłrio da pasta piper3d_monitora_florestal assegurando o funcionamento correto dos cĂłdigos contidos no projeto.

1.1 Carregando as funçÔes

1.2 Rstudio/Pacotes/versÔes/sistemas operacionais

A tabela aseguir Ă© uma referĂȘncia para as versĂ”es dos pacotes utilizados no nesse projeto. Para garantir a reprodução dos cĂłdigos, Ă© importante que o R e os pacotes usados no projeto apresentem as configuraçÔes mĂ­nimas contidas na tabela 1.

# gerar informaçÔes sobre os pacotes carregados
info <- sessionInfo()

# gerar tabela com os pacotes e versÔes
tribble(
  ~Pacotes,                         ~VersĂŁo,
  version$language,                 version$version.string,
  info$otherPkgs$dplyr$Package,     info$otherPkgs$dplyr$Version,
  info$otherPkgs$Distance$Package,  info$otherPkgs$Distance$Version,
  info$otherPkgs$DT$Package,        info$otherPkgs$DT$Version,
  info$otherPkgs$forcats$Package,        info$otherPkgs$forcats$Version,
  info$otherPkgs$flextable$Package, info$otherPkgs$flextable$Version,
  info$otherPkgs$ggplot2$Package,     info$otherPkgs$ggplot2$Version,
  info$otherPkgs$ggpubr$Package,     info$otherPkgs$ggpubr$Version,
  info$otherPkgs$here$Package,     info$otherPkgs$here$Version,
  info$otherPkgs$lubridate$Package, info$otherPkgs$lubridate$Version,
  info$otherPkgs$mrds$Package,     info$otherPkgs$mrds$Version,
  info$otherPkgs$plotly$Package,    info$otherPkgs$plotly$Version,
  info$otherPkgs$purrr$Package,     info$otherPkgs$purrr$Version,
  info$otherPkgs$readr$Package,     info$otherPkgs$readr$Version,
  info$otherPkgs$readxl$Package,     info$otherPkgs$readxl$Version,
  info$otherPkgs$stringi$Package,     info$otherPkgs$stringi$Version,
  info$otherPkgs$stringr$Package,     info$otherPkgs$stringr$Version,
  info$otherPkgs$tibble$Package,    info$otherPkgs$tibble$Version,
  info$otherPkgs$tidyr$Package,     info$otherPkgs$tidyr$Version,
  info$otherPkgs$tidyselect$Package,info$otherPkgs$tidyselect$Version
) |> 
  flextable::qflextable() |> 
  flextable::set_caption(
    "Tabela 1 - configuração de pacotes necessårios e respectivas versÔes mínimas que devem ser utilizadas para reproduzir os códigos"
  )
Tabela 1 - configuração de pacotes necessårios e respectivas versÔes mínimas que devem ser utilizadas para reproduzir os códigos

Pacotes

VersĂŁo

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[NULL]]

[[NULL]]

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[character]]

[[NULL]]

[[NULL]]

[[character]]

[[character]]

[[character]]

[[character]]

1.3 Cuidados com a planilha .xlsx que serĂĄ importada (para que mantenha o padrĂŁo da planilha de referĂȘncia do ICMBio)

A primeira função utlizada, carregar_dados_brutos_xlsx(), irĂĄ carregar a planilha em formato excel, Planilha Oficial consolidada de Masto-aves 2014-21 Validada CEMAVE CPB CENAP.xlsx, e gera automaticamente o arquivo dados_brutos.rds na pasta data-raw. A função seguinte a ser utilizada, carregar_dados_completos() que irĂĄ carregar o arquivo dados_brutos.rds. Essa função foi escrita para carrega os dados e operar uma sĂ©rie de transformaçÔes para devolvĂȘ-lo no formato padronizado do programa DISTANCE para Windows. Portanto, para garantir a reprodutibilidade dos cĂłdigos produzidos em versĂ”es atualizadas da base de dados do Monitora, Ă© importante tomar alguns cuidados.

O primeiro e mais importante cuidado Ă© manter a consistĂȘncia dos nomes das colunas em versĂ”es atualizadas da base de dados do Monitora. AlĂ©m de carregar os dados, a função carregar_dados_completos() aplica uma sĂ©rie de transformaçÔes nas colunas. Seus nomes sĂŁo alterados, e a essas sĂŁo atribuĂ­dos tipos apropriados (data, caracter, fator, inteiro e numĂ©rico), linhas sĂŁo eliminadas e novas colunas sĂŁo gereadas. Para exemplificar, veja o cĂłdigo abaixo. Ele foi escrito para executar as primeiras transformaçÔes nos dados e constitui o corpo da função carregar_dados_filtrados().

# carregar a base de dados do Monitora
dados_brutos <- carregar_dados_brutos_xlsx()

# gerar o data.frame desejado reproduzindo as transformaçÔes realizadas pela função carregar_dados_completos()
dados_filtrados <- dados_brutos |>  
  # selecionar as colunas necessĂĄrias para as analises, padronizando os nomes para o formato DISTANCE
  dplyr::select(
    uc_code = CDUC,
    uc_name = `Local - Nome da Unidade de Conservacao`,
    ea_number = `Numero da Estacao Amostral`,
    ea_name = `Nome da EA`,
    season = `Estacao do ano`,
    sampling_day = `data da amostragem`,
    day_effort = `Esforco de amostragem tamanho da trilha (m)`,
    sp = `Especies validadas para analise do ICMBio`,
    distance = `distancia (m)     do animal em relacao a trilha`,
    group_size = `n de animais`,
    observadores = `nome dos observadores`
  ) |>
  # atribuir os tipos corretos Ă s colunas e criar novas colunas
    dplyr::mutate(
      uc_category = stringi::stri_extract_first_words(
      uc_name
    ),
    # abrevia o nome das UCs
    uc_name_abv = forcats::lvls_revalue(
      uc_name,
      new_levels = c(
        "ETM", "EM", "EN", "ESGT", "FJ", "PCV", "PA", "PSBoc", "PSBod", "PSC",
        "PSM", "PSC", "PSD", "PSP", "PSO", "PPN", "PCO", "PI", "PJaĂș", "PJur",
        "PMR", "PS", "PV", "PCA", "PMT", "RG", "RJ", "RTap", "RU", "RG",
        "RTrom", "RAT", "RBA", "RCI", "RCM", "RRC", "RROP", "RIA", "RRA", "RTA"
      )
    ),
      # atribuir o tipo data Ă  coluna sampling_day
      year = lubridate::year(
        sampling_day
      ),
      # atribuir o tipo fator Ă s colunas do tipo caracter
      across(
        where(
          is.character
        ),
        as.factor
      ),
      # substituir separadores de nome por ","
      novo = stringr::str_replace_all(
        observadores, 
        " e ",
        ", "
      ),
      # substituir separadores de nome por ","
      novo = stringr::str_replace_all(
        novo, 
        " E ",
        ", "
      ),
      # substituir separadores de nome por ","
      novo = stringr::str_replace_all(
        novo, 
        "/",
        ", "
      ),
      # substituir separadores de nome por ","
      novo = stringr::str_replace_all(
        novo, 
        ";",
        ", "
      ),
      # substituir separadores de nome por ","
      novo = stringr::str_replace_all(
        novo, 
        " a ",
        ", "
      ) 
    ) |>
  # transformar os nomes dos observadores da coluna novo em colunas individuais
tidyr::separate_wider_delim(
  novo, 
  ",",
  names = c(
    "obs1", "obs2", "obs3", "obs4", "obs5", "obs6"
  ),
  too_few = "align_start"
) |> 
  # gerar uma nova coluna number_observers com o nĂșmero total de observadores em um mesmo transecto
  dplyr::mutate(
    # se o valor da observação é diferente de NA, substituir por 1, se for NA, substituir por 0
    obs1 = ifelse(!is.na(obs1), 1, 0),
    obs2 = ifelse(!is.na(obs2), 1, 0),
    obs3 = ifelse(!is.na(obs3), 1, 0),
    obs4 = ifelse(!is.na(obs4), 1, 0),
    obs5 = ifelse(!is.na(obs5), 1, 0),
    obs6 = ifelse(!is.na(obs6), 1, 0),
    # gera nova coluna number_observers a partir da soma das colunas de observadores individuais
    number_observers = obs1 + obs2 + obs3 + obs4 + obs5 + obs6
  ) |> 
  # agrupar os dados pelas colunas ea_name e sampling_day
  group_by(
    ea_name, 
    sampling_day
  ) |> 
  # aninhar as observaçÔes agrupadas uem listas
  nest() |> 
  # completar com o valor correto as linhas vazias das da variĂĄvel day_effort
  mutate(
    day_effort2 = purrr::map(
      data, \(.x) rep(
        .x$day_effort[
          !is.na(
            .x$day_effort
          )
        ][1]
      )
    )
  ) |> 
  # desanihar os dados
  unnest(
    c(
      data, 
      day_effort2
    )
  ) |> 
  # desagrupar os dados
  ungroup() |> 
  # selecionar as colunas desejadas e excluir as indesejadas
  select(
    tidyselect::starts_with(c("uc", "ea")),
    season,
    year,
    sampling_day,
    day_effort = day_effort2,
    sp:number_observers,
    -day_effort,
    -tidyselect::starts_with("obs")
  ) |>
  # filtrar os dados pela UC e espécie desejadas
    dplyr::filter(
      uc_name == "Resex Tapajos-Arapiuns",
      sp == "Dasyprocta croconota"
    ) |> 
  relocate(
    uc_category,
    .before = uc_name
  ) |> 
  relocate(
    uc_name_abv,
    .after = uc_name
  )

# gerar tabela dinĂąmica dos dados completos
dados_filtrados |> 
  slice(
    1:1000
  ) |> 
  datatable(
    filter = list(
      position = "top"
    )
  )

O trecho do código que vai da linha 96 a 106 serve selecionar apenas as colunas de interesse presente nos dados originais. Note que os nomes das planilhas originais constam nesse trecho. Caso o nome de qualque uma dessas colunas seja alterado a função deixarå de funcionar.

Outro aspecto importante Ă© a presença de observaçÔes nĂŁo preenchidas (ex. cĂ©lulas vazias) nos dados originais. A função foi desenha para resolver alguns problemas presentes nos dados originais. Por exemplo, nas o trecho do cĂłdigo das linhas 194 a 210 as observaçÔes vazias (NAs) sĂŁo substituidas pelo valor correto na coluna day_effort. Essa correção continnuarĂĄ sendo realizada em versĂ”es atualizadas dos dados do Monitora. PorĂ©m, se outras colunas alĂ©m das que estĂŁo sendo corrigidas possuirem observaçÔes vazias os dados serĂŁo carregados e transformados, porĂ©m outras funçÔes podem ter o seu funcionamento comprometido. Por exemplo, funçÔes de visualização e do pacote Distance que podem nĂŁo funcionar devido a ausĂȘncia de observação.

Dentre todas as funçÔes de carregamento de dados, apenas carregar_dados_brutos_xlsx() carrega a base de dados originais do Monitora, diretamente do diretório data-raw/monitora_masto_aves_2023_04_04.xlsx. Ao mesmo tempo que carrega e transforma os dados, essa função gera uma versão em um formato mais leve, .rds, no diretório data-raw (data-raw/monitora_masto_aves_2023_04_04.rds). A função seguinte no fluxo de trabalho carrega a base a partir dessa versão mais leve. Logo, sempre que houver atualizaçÔes no arquivo original de dados brutos é necessårio iniciar a rotina de carregamento de dados necessariamente com a função carregar_dados_brutos_xlsx().

2 PARTE II – Carregando os dados para o R

2.1 Dados brutos

NĂŁo precisa se assustar com a infinidade de cĂłdigos no exemplo acima. Eles foram utilizados apenas para ilustrar que construir essas funçÔes facilita a execução e a reprodutibilidade das anĂĄlise dos dados do Monitora. Para cada tarefa existe uma função cujo funcionamento necessita o preenchimento de alguns argumentos, ou mesmo de nenhum (embora seja sempre possĂ­vel fornecĂȘ-los). Por traz das cortinas, as funçÔes executam as tarafas necessĂĄrias para se obter o resultado desejado. Por exemplo, o mesmo resultado pode ser obtido utilizando apenas duas funçÔes: carregar_dados_brutos_xlsx()e gerar_tabdin_dados_brutos().

# carregar dados brutos
dados_brutos <- carregar_dados_brutos_xlsx()

# gerar tabela dinamica dos dados brutos
gerar_tabdin_dados_brutos()

A função gerar_tabdin_dados_brutos(), por configuração, gera uma tabela dinĂąmica com 1000 linhas. VocĂȘ pode controlar o nĂșmero de linhas pelo argumento n_linhas =. Mas atenção! Ela nĂŁo funcionarĂĄ com um nĂșmero superior a 4.500 linhas. Ao mudar a entrada de dados usando o argumento dados =, certifique-se de que seu nĂșmero de linhas nĂŁo exceda esse limite (ex. 4.500).

gerar_tabdin_dados_brutos(
  n_linhas = 1:4500
)

2.2 Dados completos

# carregar dados para o R
dados_completos <- carregar_dados_completos() 

# gerar tabela dinamica dos dados completos
gerar_tabdin_dados_completos()

2.3 Dados filtrados

# carregar dados para o R
dados_filtrados <- carregar_dados_filtrados()

# gerar tabela dinĂąmica dos dados fitrados
gerar_tabdin_dados_filtrados()

3 Parte III – Transformando dados para Distance

3.1 Dados completos no formato Distance

# transformar os dados para o formato do Distance
dados_distanceR_completo <- transformar_para_distanceR_covariaveis()

# gerar tabela dinamica dos dados no formato do distance do R
gerar_tabdin_dados_selecionados_distanceR_cov()

4 PARTE IV – Explorando e selecionando os dados para as análises

Apresentamos abaixo um conjunto de ferramentas que permite diversas formas de explorar todo o conjunto de dados.

4.1 Selecionando os melhores espécies modelo de estudo de acordo com os dados

Alguns cuidados devem ser tomados na preparação dos dados antes de serem analisados. O primeiro deles é o cuidado taxonÎmico. Para os dados do Monitora recomenda-se o uso dos dados das espécies validadas para anålise pelo ICMBio, conforme o modelo utilizado para este fluxo de trabalho.

Alguns problemas com os dados, que podem trazer efeitos indesejados sobre as anålises, podem ser detectados durante a fase de exploração. Ao selecionar os dados que serão analisados, é importante observar os seguintes aspectos:

SuficĂȘncia Amostral - nĂșmero de ocorrĂȘncias por espĂ©cie

Para que o mĂ©todo de anĂĄlise por distĂąncia possa ser utilizado para estimativas baseadas em modelos, sĂŁo recomendadas quantidades mĂ­nimas de registros de ocorrĂȘncia e de transectos (Unidades Amostrais). Segundo BUCKLAND et. al. (2015), o nĂșmero mĂ­nimo sugerido de animais ou grupos (ocorrĂȘncias) Ă© de 60 – 80 animais (ou grupos) quando a amostragem Ă© feita pelo mĂ©todo dos transectos lineares. É possĂ­vel utilizar nĂșmeros menores que estes para realizar as anĂĄlises, porĂ©m deve-se ter o cuidado de verificar se as funçÔes de detecção estĂŁo bem modeladas.

Para dados que serĂŁo estratificados (divididos em subconjuntos), estes nĂșmeros recomendados se aplicam a cada subconjunto. Isso ocorre porque as funçÔes de detecção serĂŁo modeladas para cada estrato (p.ex.Region.Label), alĂ©m da função de detecção para os dados globais. Um exemplo seria a anĂĄlise dos dados, para uma mesma espĂ©cie, em diferentes UCs. Neste caso, o ideal seria ter a suficiĂȘncia amostral mĂ­nima em cada UC para usar estratificação e estimar abundĂąncias e densidades em cada uma das UCs.

SuficiĂȘncia amostral - rĂ©plicas e repetiçÔes

Para que haja uma boa cobertura da ĂĄrea de estudo e tambĂ©m uma boa quantidade de amostras independentes para estimar as abundĂąncias e densidades das espĂ©cies, Ă© desejĂĄvel um nĂșmero satisfatĂłrio de rĂ©plicas independentes. Segundo BUCKLAND et al. (2015), o nĂșmero mĂ­nimo de rĂ©plicas independentes para os transectos deve ser de 10-20, o que deve aumentar para espĂ©cies cujas populaçÔes sĂŁo distribuĂ­das em manchas.

De forma geral, para cada UC, o nĂșmero de rĂ©plicas do Programa Monitora estĂĄ abaixo do recomendado. O delinamento amostral atual para a compontente Florestal do subprograma Terrestre estabelece um nĂșmero mĂ­nimo de trĂȘs EstaçÔes Amostrais por Unidade de Conservação, o que Ă© o caso de muitas UCs, chegando ao mĂĄximo de 9 estaçÔes amostrais por UC. O baixo nĂșmero de rĂ©plicas espaciais idependentes nĂŁo chega a ser um problema na estimativa de densidade da Área Coberta pela amostragem, mas limita uma boa estimativa de densidade total para a Unidade de Conservação.

Um outro aspecto relacionado a amostragem Ă© o nĂșmero de repetiçÔes por transecto. Segundo BUKLAND et al (2001, pg 79), as repetiçÔes devem ser incorporadas no esforço amostral multiplicando-se o nĂșmero de vezes que o transecto foi percorrido pelo comprimento do transecto. A mesma recomendação Ă© dada pelo Curso Online em Distance Sampling link. Esse ajuste no esforço amostral nĂŁo deve ter grandes consequĂȘncias para um baixo nĂșmero de repetiçÔes. PorĂ©m, nĂșmeros altos de amostragens repetidas e nĂŁ independentes levam a uma inflagem no tamanho da ĂĄrea coberta. Apenas para ilustar com um exemplo, para os dados da cutia Dasyprocta croconota da Resex TapajĂłs-Arapinuns, a Estação Amostral Boim foi percorrida durante 70 dias de amostragem. Isso significa que ajustando o comprimento do transecto de 5 km pelo nĂșmero de repetiçÔes, o esforço amostral passou para 350 km. A ĂĄrea coberta aumentou em 70x, o que terĂĄ consequĂȘncias sobre a estimativa densidade, que tenderĂĄ a ser subestimada. AlĂ©m disso, o coeficiente de variação das estimativas de taxa de encontro, abundĂąncia e densidade tambĂ©m tenderĂŁo a aumentar pelo efeito da variaçÔes temporais entre as amostragens.

Uma forma de lidar com o excesso de amostragens repetidas Ă© tratar as repetiçÔes como efeitos aleatĂłrios dos modelos. Isso requer o uso de abordagens que vĂŁo alĂ©m da amostragem por distĂąncia convecional, como o uso de Mixed Effect Models e Modelos HierĂĄrquicos (p. ex. OEDEKOVEN et al. 2013, 2014). Essas abordagens ainda nĂŁo foram implementadas em nosso fluxo de trabalho atĂ© a presente versĂŁo e pretendemos testar os cĂłdigos para esta abordagem utilizando o pacote unmarked atĂ© o final da vigĂȘncia do presente projeto.

Distribuição de frequĂȘncia das ocorrĂȘncias em relação Ă  distĂąncia - efeitos indesejados

A distribuição ideal das frequĂȘncias de ocorrĂȘncia em relação Ă  distĂąncia deve apresentar as seguintes caracterĂ­sticas: a frequĂȘncia de ocorrĂȘncia deve ser maior prĂłximo a zero, apresentar um longo platĂŽ (ombro), e decair gradativamente com o aumento da distĂąncia. Isso significa que os animais sĂŁo totalmente detectĂĄveis na distĂąncia zero, seguem sendo bem detectĂĄveis a distĂąncias curtas e vĂŁo perdendo detectabilidade gradativamente com o aumento da distĂąncia.

Por isso, uma das etapas exploratĂłrias Ă© avaliar o histograma de frequĂȘncias de ocorrĂȘncia ao longo da distĂąncia em relação ao transecto (opção abaixo). Algumas distribuiçÔes indicam problemas nos dados que podem dificultar o ajuste das funçÔes de detecção. Tais como:

Pico de ocorrĂȘncias prĂłximos Ă  distĂąncia zero - spike near zero distance

Isso ocorre quando o nĂșmero de observaçÔes prĂłximos Ă  distĂąncia zero Ă© inflado em relação Ă s demais distĂąncias. O efeito grĂĄfico serĂĄ um pico no histograma em zero ou prĂłximo a zero, conforme o exemplo abaixo para os dados extraĂ­dos das cutias (Dasyprocta croconota) na Resex TapajĂłs-Arapiuns.

Distribuicao de Frequencia para Dasyprocta croconota na Resex Tapajos-Arapiuns

Este tipo de distribuição foi predominante para as espĂ©cies com o maior nĂșmero de ocorrĂȘncia nos dados de aves e mamĂ­feros do Programa Monitora Florestal. Acreditamos que existem dois fatores que podem estar causando esse acĂșmulo de dados em zero ou prĂłximo a ele. Um deles seria um viĂ©s para avistamento de animais na trilha em ambientes de floresta. As trilhas podem atrair animais, e tambĂ©m oferecem melhor visibilidade em relação Ă  floresta, especialmente se o sub-bosque for denso. O outro fator seria um possĂ­vel arredondamento nas distĂąncias prĂłximas a zero, o que pode gerar um “amontoamento” nos dados (heaping). Recomenda-se que valores de distĂąncia perpendicular nunca sejam arredondados.

Resposta evasiva das espécies em relação ao observador

Para espĂ©cies que podem apresentar resposta de deslocamento em relação ao observador, um dos efeitos indesejados nos dados Ă© o deslocamento das maiores frequĂȘncias de observaçÔes para as distĂąncias perpendiculares intermediĂĄrias ao mesmo tempo que as frequĂȘncias prĂłximas ao observador sĂŁo baixas. Uma alternativa, nesse caso, Ă© constranger a função de deteção para monotonicidade, evitando que ela suba para se ajustar ao pico de frequĂȘncia nas distĂąncias intermediĂĄrias.

Viés de tamanho de grupo

Um dos efeitos que pode ocorrer para espĂ©cies que formam grupos, Ă© que grupos menores perdem a detectabilidade mais fĂĄcil do que grupos maiores com o aumento da distĂąncia. Esse viĂ©s pode ser testado na exploração dos dados das covariĂĄvies, plotando-se um grĂĄfico de tamanho de grupo pela distĂąncia. Caso o viĂ©s ocorra, serĂĄ uma observada uma tendĂȘncia de registros somente de grupos maiores nas distĂąncias maiores. NĂłs adotamos a estratĂ©gia de tratar tamanho de grupo como covariĂĄvel para espĂ©cies que formam grupos. Neste caso, ao mesmo tempo que lidamos com o efeito do tamanho do grupo na detectabilidade, incorporamos tambĂ©m o tamanho do grupo nas estimativas de densidade e abundĂąncia.

4.1.1 Exploração e seleção de dados

4.1.1.1 Aspectos relacionados ao nĂșmero total de observaçÔes

4.1.1.2 Quantas observaçÔes foram validadas para quais níveis taxonÎmicos?

Essas operaçÔes são realizadas sobre a tabela de dados dados_completos pois os dados que foram transformados para o formato do distace no R não possuem a coluna validation, necessåria para essas opereaçÔes. Mais a frente o procedimento de como obter os dados selecionados e transformatos para o formato das anålises serå demonstrado.

# contar observaçÔes validadas ao nível de espécie
n_obs_validadas <- contar_n_obs_validadas()
n_obs_validadas
[1] 19747   307  6187    14   165

Foram selecionadas apenas as observaçÔes validadas ao nível de espécie, somando um total 19747 observaçÔes.

# gerar grĂĄfico com nĂșmero observaçÔes validadas para cada nĂ­vel taxonĂŽmico
plotar_n_obs_validadas_interativo()

Finalmente chegamos ao subconjunto dos dados que serå utilizado para selecionar quais espécies serão analisadas.

# gerar tabela de dados selecionados
dados_selecionados <- carregar_dados_selecionados()

# gerar tabdin dados_selecionados 
gerar_tabdin_dados_selecionados()

4.1.1.3 Quantas unidades de conservação ao todo?

# contar nĂșmero total de UC's 
n_ucs <- contar_n_uc()
n_ucs
[1] 38

Os dados são provenientes de 38 unidades de conservação ao todo.

4.1.1.4 Quantas espécies ao todo?

n_sp <- contar_n_sp()
n_sp
[1] 165

Até aqui temos dados para 165 espécies.

4.1.1.5 Quantas observaçÔes por unidade de conservação ao todo?

# contar nĂșmero de observaçÔes por UC
n_obs_uc <- contar_n_obs_uc()

# gerar tabdin
gerar_tabdin_n_obs_uc()
# plotar o nĂșmero de observaçÔes por UC
plotar_n_obs_uc_interativo()

4.1.1.6 Quantas observaçÔes para cada espécie?

# contar total sp
n_obs_sp <- contar_n_obs_sp()
n_obs_sp
# gerar tabela dinĂąmica com o nĂșmero total de obsevaçÔes por espĂ©cie
gerar_tabdin_n_obs_sp()
# plotar o o nĂșmero de observaçÔes por UC
plotar_n_obs_sp_interativo()

Tabela interativa para consulta do nĂșmero de observaçÔes por espĂ©cie.

gerar_tabdin_n_obs_sp()

4.1.1.7 Quais e quantas observaçÔes para cada espécie por unidades de conservação?

# gerar tabela com o nĂșmero de observaçÔes por espĂ©cie e por UC
n_obs_sp_uc <- contar_n_obs_sp_uc()
n_obs_sp_uc
gerar_tabdin_n_obs_sp_uc()

4.1.1.8 Quantas unidades de conservação foram amostradas em cada ano?

Gerar função para tabela dinùmica.

gerar_tabdin_n_uc_ano()

4.1.1.9 Quais unidades de conservação foram amostradas em um maior nĂșmero de anos?

n_ano_uc <- contar_n_ano_uc()
`summarise()` has grouped output by 'uc_name'. You can override using the `.groups` argument.
n_ano_uc  
gerar_tabdin_n_ano_uc()

4.1.1.10 Quantas observaçÔes foram realizadas por UC em cada ano?

n_obs_uc_ano <- contar_n_obs_uc_ano()
n_obs_uc_ano

Tabela interativa para consultar quantas observaçÔes foram realizadas por ano em cada UC

gerar_tabdin_n_obs_uc_ano()

4.1.1.11 Quantas observaçÔes para cada espécies por ano?

n_obs_sp_ano <- contar_n_obs_sp_ano()
n_obs_sp_ano

Tabela interativa para consultar quantas observaçÔes foram realizadas para cada espécie em cada ano

gerar_tabdin_n_obs_sp_ano()

4.1.1.12 Quantas observaçÔes para cada espécies por UC e por ano?

n_obs_sp_uc_ano <- contar_n_obs_sp_uc_ano()
n_obs_sp_uc_ano

Tabela interativa para consultar quantas observaçÔes foram realizadas para cada espécie em cada ano

gerar_tabdin_n_obs_sp_uc_ano()

4.1.1.13 Quantas observaçÔes para cada espécies por UC, por estação e por ano?

n_obs_sp_uc_estacao_ano <- contar_n_obs_sp_uc_estacao_ano()
n_obs_sp_uc_estacao_ano
gerar_tabdin_n_obs_sp_uc_estacao_ano()

4.1.1.14 Avaliando nĂșmero de rĂ©plicas (EstaçÔes Amostrais) por UC

4.1.1.15 Selecionando melhores modelos de estudo considerando estratificação espacial/temporal – se hĂĄ suficiĂȘncia amostral (60-80 observaçÔes) por estrato

  • PossĂ­veis estratificaçÔes espaciais

  • EAs/UCs

  • UCs/EspĂ©cies

  • PossĂ­veis estratificaçÔes temporais

  • EspĂ©cie/UC/Ano

4.1.1.16 Avaliando distĂąncia de truncamento

  • GrĂĄficos de distribuição das frequĂȘncias de ocorrĂȘncia x distĂąncia perpendicular.

4.1.1.17 Distribuição de distùncias

# gerar o gråfico exploratório da distribuição de distùncias perpendiculares para a espécies Dasyrocta croconota na Resex Tapajós-Arapiuns
fig <- dados_filtrados |>
  # excluir NA's da variĂĄvel distance
  tidyr::drop_na(distance) |> 
  plotar_distribuicao_distancia_interativo()

fig

4.1.1.18 Avaliando covariĂĄveis

As covariĂĄveis devem ser pensadas de acordo com o grupo taxonĂŽmico. EspĂ©cies que formam grupos devem ter a covariĂĄvel ‘size’. As estratĂ©gias de estratificação podem ser substituĂ­das por covariĂĄveis tambĂ©m (estratos espaciais/ ano). Como covariĂĄvel temporal, pode se pensar em usar, alĂ©m do ano, a estação do ano (season), o horĂĄrio do dia (para animais que variam a atividade). O horĂĄrio do dia pode ser convertido em tempo apĂłs nascer do sol (como no exemplo). Mas para isso Ă© necessĂĄrio criar essa variĂĄvel no dataset. E nĂŁo Ă© trivial porque precisa saber o horĂĄrio de nascer do sol em cada dia/local para calcular.

5 PARTE V – Ajustando os modelos

5.1 Fluxo de anĂĄlise dos dados:

A seguir, apresentamos o fluxo de anĂĄlise dos dados que envolve a fase exploratĂłria, truncamento, ajuste e avaliação de modelos e estimativas de abundĂąncia e densidade para as espĂ©cies que selecionamos como modelo. Usamos como critĂ©rios de seleção tanto o nĂșmero de ocorrĂȘncias por Unidade de Conservação quanto a distribuição das frequĂȘncias de observação, nos casos em que isso foi possĂ­vel. De forma geral, as espĂ©cies com nĂșmero satisfatĂłrio de ocorrĂȘncias (>60), apresentaram pico de observaçÔes prĂłximos a zero.

NĂłs usamos como modelo para este fluxo Dasyprocta croconota da Resex TapajĂłs-Arapiuns, pelo grande nĂșmero de ocorrĂȘncias para uma mesma UC. NĂłs implementamos duas estratĂ©gias para lidar com os efeitos indesejados nos dados: pico prĂłximo a zero (heaping near zero) e nĂșmero excessivo de repetiçÔes amostrais na mesma trilha. Para lidar com os picos, testamos o uso dos dados com distĂąncias exatas e distĂąncias agrupadas. Para lidar com as repetiçÔes, testamos a anĂĄlise dos dados com todas as repetiçÔes e com o nĂșmero de repetiçÔes reduzidas. Essas estratĂ©gias estĂŁo descritas em Fluxos 1-3. No primero fluxo, comentamos tambĂ©m as escolhas feitas e os resultados obtidos. Os demais fluxos sĂŁo repetiçÔes deste primeiro fluxo, porĂ©m com mudança na estrutura dos dados.

Especies com maior numero de ocorrencias/UC possibilitam testar, posteriormente, estratificaçÔes nos dados, preservando um nĂșmero de ocorrĂȘncias satisfatĂłrio dentro dos estratos. Por isso começamos apresentando um fluxo completo de anĂĄlise, incluindo Amostragem por DistĂąncia Convencional, Amostragem por DistĂąncia com MĂșltiplas CovariĂĄveis e Amostragem por DistĂąncia com Estratificação nos dados com as espĂ©cies com maior nĂșmero de ocorrĂȘncia.

5.2 Espécie Modelo - Dasyprocta croconota - Resex Tapajós Arapiuns

Fonte: biolib.cz

Essa Ă© a espĂ©cie com o mair nĂșmero de ocorrĂȘncias para uma mesma UC. Apresentou, como a maioria das espĂ©cies em diferentes UCs, um pico de ocorrĂȘncias prĂłximo a zero.

5.2.1 Carregar Dados

Para selecionar do conjunto de dados da espécie e a Unidade de conservação de interesse, usar a função transforma_para_distanceR_com_repeticao_filtra_uc_sp(), especificando o nome da Unidade de conservação através do argumento nome_uc e o nome da espécie através do argumento nome_sp.

# carregar dados
cutia_tap_arap <- transforma_para_distanceR_com_repeticao_filtra_uc_sp(
  nome_uc = "Resex Tapajos-Arapiuns",
  nome_sp = "Dasyprocta croconota"
) 

cutia_tap_arap

5.2.2 Amostragem por DistĂąncia Convencional

5.2.2.1 Fluxo 1 - Distùncias exatas com todas as repetiçÔes

5.2.2.1.1 Plotando o histograma das frequĂȘncias de ocorrĂȘncia pela distĂąncia

O histograma interativo estĂĄ disponĂ­vel no app em Shiny app_distancia_interativo.R. A distribuição dos dados no histograma permite observar um pico de observaçÔes prĂłximo a zero, alĂ©m de uma considerĂĄvel perda em detectabilidade a partir dos 20m. Vamos testar diferentes proporçÔes de truncamento. É possĂ­vel alterar a binagem dos histogramas atravĂ©s do argumento largura_caixa. Neste exemplo ajustamos para 1, o que facilita a observação de picos de detecação e efeitos de heaping nos dados.

cutia_tap_arap |> 
  drop_na(distance) |> 
plotar_distribuicao_distancia_interativo(largura_caixa = 1)
5.2.2.1.2 Testando distĂąncia de truncamento (w)

Vamos explorar diferentes distùncias de truncamento para um mesmo modelo de distribuição half-normal. Optamos por truncar os dados pela percentagem para padronizar a rotina para diferentes espécies. Buckland et al. (2001) sugere um corte entre 5-10% das observaçÔes detectadas nas maiores distãncias. Vamos selecionar o valor de corte pelo modelo com melhor ajuste. Para os dados, testamos as seguintes proporçÔes de corte de dados: 5, 10, 15, 20 e 25% das observaçÔes mais distantes. Geramos uma tabela comparando os modelos e também plotamos os gråficos dos modelos ajustados para os dados truncados.

5.2.2.1.2.1 Tabela com resumo comparativo dos modelos
# conduz a selecao da melhor distancia de truncamento a partir do ajsute de modelos com funcao de deteccao half-normal sem termos de ajuste
cutia_tap_arap_dist_trunc <- cutia_tap_arap |> 
  selecionar_distancia_truncamento()

cutia_tap_arap_dist_trunc$selecao
5.2.2.1.2.2 Plotando o histograma com os dados truncados.

Histogramas resultantes dos modelos, com todas as distùncias de truncagem, para auxiliar na seleção da melhor distãncia.

plotar_funcao_deteccao_selecao_distancia_truncamento(cutia_tap_arap_dist_trunc)

ApĂłs avaliar tanto o ajuste dos modelos quanto os grĂĄficos, optamos por truncar 15% das observaçÔes feitas nas maiores distĂąncias. Apesar dos melhores valores de AIC e de ajuste do CramĂ©r-von Mises para 25%, os histogramas com modelos ajustados para 25%, 20% e 15% apresentaram modelos quase lineares e com uma grande probabilidade de deteção nos Ășltimos intervalos de distĂąncia. O modelo com corte de 10% apresentou uma curva decrescente e nĂŁo tendeu a zero nas Ășltimas distĂąncias. JĂĄ no modelos para 5% as funçÔes de deteção tendem a zero nos Ășltimos intervalos de distĂąncia. O corte de 10% das observaçÔes mais distantes resultou em uma distĂąncia de truncamento de 15m.

5.2.2.1.3 Ajustando diferentes modelos de funçÔes de deteção

As funçÔes de deteção sĂŁo ajustadas atravĂ©s da função ds() no pacote Distence para o R. Para otimizar o fluxo de ajuste de funçÔes, empacotamos as diferentes combinaçÔes de funçÔes chave e termos de ajustes em trĂȘs funçÔes. SĂŁo elas: ajuste_modelos_distance_unif(), para distribuição uniforme sem termos de ajuste e com termos de ajuste do tipo cosseno e polinomial simples, ajuste_modelos_distance_hn() para distribuição half-normal sem termos de ajuste e com termos de ajuste do tipo cosseno e polinomial de hermite; e ajuste_modelos_distance_hr() para distribuição hazard-rate sem termos de ajuste e com termos de ajuste do tipo cosseno e polinomial simples. Para definir a distĂąncia de truncamento dos dados Ă© necessĂĄrio fornecer o argumento truncamento, que pode ser definido tanto em percentagem de corte dos dados quanto em valor de distĂŁncia.

5.2.2.1.3.1 Uniforme com termos de ajuste Cosseno e polinomial simples
# ajustando a função de detecção uniforme para um truncamento de 10% dos dados
cutia_tap_arap_unif <- cutia_tap_arap |> 
  ajuste_modelos_distance_unif(truncamento = "10%")

Dentre as combinaçÔes de termos de ajustes para a função chave de distribuição uniforme, o Distance selecionou o modelo uniforme com ajuste polinomial simples, com as ordens 2, 4 e 6. Ele mantĂ©m esse modelo, e descarta os demais. Os Warnings indicando que a função de detecção nĂŁo Ă© estritamente monotĂŽnica avisam que os dados nĂŁo foram constrangidos para a monotonicidade. Isso porque o uso de termos de ajustes, especialmente de ordens acima de 2, podem levar Ă  perda da monotonidade (a curva pode se tornar crescente em algum momento, o que nĂŁo Ă© desejado). É preciso avaliar se a fala desse constragimento levou efetivamente Ă  perda da monotonicidade ao olhar os grĂĄficos de ajuste dos modelos.

5.2.2.1.3.2 Half-Normal sem termos de ajuste e com termos de ajuste Cosseno e Polinomial de Hermite
# ajustando a função de detecção half-normal para um truncamento de 10% dos dados
cutia_tap_arap_hn <- cutia_tap_arap |> 
  ajuste_modelos_distance_hn(truncamento = "10%")

Neste caso, o modelo selecionado pelo Distance foi o Half-normal sem nenhum termo de ajuste.

5.2.2.1.3.3 Hazard-rate sem termos de ajuste e com termos de ajuste Cosseno e Polinomial de Hermite
# ajustando a função de detecção hazard-rate para um truncamento de 10% dos dados
cutia_tap_arap_hr <- cutia_tap_arap |> 
  ajuste_modelos_distance_hr(truncamento = "10%")

Aqui o melhor modelo selecionado pelo Distance foi o Hazard-rate sem os termos de ajuste. Nesse caso, também hå um warning para o problema na distribuição dos dados, que apresentam um pico próximo a distùncia zero e não são bem ajustados pelo hazard-hate.

5.2.2.1.4 Comparando os modelos

Para comparar os modelos Ă© preciso avaliar trĂȘs critĂ©rios: AIC, ajuste e forma das funçÔes nos grĂĄficos e bondade de ajuste. O pacote distance possui a função summarize_ds_modelsque gera uma tabela com os modelos para comparação de alguns parĂąmetros: a primeira coluna Model, indica as funçÔes chaves e respectivos termos de ajuste; a coluna Formula apresenta as covariĂĄveis, quando incluĂ­das no modelo, ou ~1, quando nĂŁo hĂĄ covariĂĄveis; C-vM p-value vai apresentar os valores de p para o teste de bondade de ajuste de CramĂ©r-von Mises; \(\hat{P_a}\) apresenta a probalidade de deteção global estimada para cada modelo; se(\(\hat{P_a}\)) apresenta o erro padrĂŁo para as estimativas de probabilidade de detecção; e \(\Delta\)AIC apresenta os valores de delta AIC.

5.2.2.1.4.1 Tabela com o resumo comparativo dos modelos
fluxo1_lista_modelos_ajustados <- list(
  `half-normal` = cutia_tap_arap_hn, 
  `hazard-rate` = cutia_tap_arap_hr, 
  `uniforme` = cutia_tap_arap_unif
)

fluxo1_selecao_funcao_deteccao_termo_ajuste <- selecionar_funcao_deteccao_termo_ajuste(fluxo1_lista_modelos_ajustados)

fluxo1_selecao_funcao_deteccao_termo_ajuste

Dentre os modelos testados, o que apresentou melhor valor de ajuste e AIC foi o hazard-rate. O ajuste do Cramér-von Mises foi consideravelmente maior que os demais (para esse tipo de teste, quanto maior o valor de p, melhor o ajuste), assim como as diferenças no delta AIC foram bastante elevadas.

5.2.2.1.4.2 Gråficos de ajuste das funçÔes de deteção às probabilidades de deteção
# gerar uma lista com os modelos selecionados ordenados do melhor para o pior modelo
fluxo1_modelos_selecionados <- list(
  cutia_tap_arap_hr$`Sem termo`,
  cutia_tap_arap_unif$`Cosseno`,
  cutia_tap_arap_hn$`Cosseno`,
  cutia_tap_arap_unif$`Polinomial simples`,
  cutia_tap_arap_hn$`Sem termo`
)

# atribuir o nome dos modelos aos itens da lista

names(fluxo1_modelos_selecionados) <- fluxo1_selecao_funcao_deteccao_termo_ajuste$Model

# plotar a probabilidade de detecção observada (barras) e a esperada (linhas e pontos)
plotar_funcao_deteccao_modelos_selecionados(fluxo1_modelos_selecionados)

Olhando para os histogramas com modelos ajustados, Ă© possĂ­vel observar o efeito do acĂșmulo de observaçÔes prĂłximo a zero. O modelo com a função chave hazard-hate sem termos de ajuste, apesar de ter apresentado o melhor valor de ajuste pelo CramĂ©r-von Mises e o melhor valor de AIC, apresentou dois problemas. As probalidades de deteção estimadas por intevalo de distĂąncia (barras cinzas), ficaram muito baixas. AlĂ©m disso, a curva da função de deteção apresenta pico na distĂąncia prĂłxima a zero, decaindo rapidamente e se aproximando de zero ao longo do eixo das distĂŁncias. Todos os outros quatro modelos tiveram ajuste e AIC bastante inferiores ao hazard-hate. Entretanto as curvas estĂŁo relativamente melhores. As curvas do segundo e terceiro modelo, uniforme com ajuste cosseno e half-normal com ajuste cosseno, respectivamente, tendem Ă  perda de monotonicidade. As duas Ășltimas curvas, para os modelos uniforme com ajuste polinomial simples e half-normal sem ajuste, nĂŁo perdem a monotonicidade. De forma geral, as probabilidades de detecção nĂŁo tĂȘm um bom ajuste abaixo da curva, e nĂŁo apresentam um decaimento gradual com a distĂąncia. Esses sĂŁo problemas inerentes Ă  distribuição dos dados.

5.2.2.1.4.3 Teste de bondade de ajuste dos modelos e Q-Q plots
bondade_ajuste_fluxo1 <- testar_bondade_ajuste(fluxo1_modelos_selecionados, plot = TRUE)
bondade_ajuste_fluxo1

Aqui são gerados Q-Q plots que permitem avaliar a qualidade do ajuste dos modelos. E também uma tabela com os resultados do Carmér-von Mises, onde W é o valor do teste e p seu valor de significùncia. Nesse caso, quanto maior o valor de p, melhor o ajuste do modelo.

5.2.2.1.5 Avaliando as estimativas de AbundĂąncia e Densidade

Aqui, sĂŁo resumidos os dados de taxa de encontro, abundĂąncia e densidade em trĂȘs tabelas.

5.2.2.1.5.1 CaracterĂ­sticas da ĂĄrea de estudo e da taxa de encontro
# gera lista contendo os modelos selecionados para cada função de detecção e termo de ajuste
fluxo1_lista_modelos_ajustados_termos <- list(
  cutia_tap_arap_hr$`Sem termo`,
  cutia_tap_arap_hn$Cosseno,
  cutia_tap_arap_unif$Cosseno,
  cutia_tap_arap_unif$`Polinomial simples`,
  cutia_tap_arap_hn$`Sem termo`
)

# ĂĄrea de estudo, tamanho da ĂĄrea de estudo, area coberta pelo esforço amostral, esforço amostral em metros, nĂșmero de detecçÔes, nĂșmero de transectos (ea), taxa de encontro, coeficiente de variação da taxa de encontro  
fluxo1_caracteristicas_area_estudo_taxa_encontro <- fluxo1_lista_modelos_ajustados_termos |> 
  gerar_caracteristicas_area_estudo_taxa_encontro(resultado_selecao_modelos = fluxo1_selecao_funcao_deteccao_termo_ajuste)

fluxo1_caracteristicas_area_estudo_taxa_encontro
5.2.2.1.5.2 Características de abundùncia, esforço e detecção
# ĂĄrea de estudo, tamanho da ĂĄrea de estudo, trilhas ou estaçÔes amostrais, esforço total em cada trilha, abundĂąncia estimada em cada estação amostral, nĂșmero de detecçÔes em cada estação amostral, ĂĄrea total amostrada
fluxo1_caracteristicas_esforco_abundancia_deteccao <- fluxo1_lista_modelos_ajustados_termos |> 
  gerar_caracteristicas_esforco_abundancia_deteccao(resultado_selecao_modelos = fluxo1_selecao_funcao_deteccao_termo_ajuste)

fluxo1_caracteristicas_esforco_abundancia_deteccao
5.2.2.1.5.3 CaracterĂ­sticas de densidade
# total, densidade estimada, erro padrão da densidade destimada, coeficiente de variação da densidade destimada, intervalo de confiança inferior e superior do coeficiente de variação, gruas de liberdade
fluxo1_caracteristicas_densidade <- fluxo1_lista_modelos_ajustados_termos |> 
  gerar_caracteristicas_densidade(resultado_selecao_modelos = fluxo1_selecao_funcao_deteccao_termo_ajuste)

fluxo1_caracteristicas_densidade

5.2.2.2 Fluxo 2 - Distùncias exatas com repetiçÔes reduzidas

5.2.2.2.1 Filtrando os dados para reduzir as repetiçÔes
dados_selecionados <- carregar_dados_selecionados()
cutia_tap_arap_quase_sem_repeticao <- transforma_para_dsitanceR_quase_sem_repeticao_filtra_uc_sp_covariavel(
  dados = dados_selecionados,
  nome_uc = "Resex Tapajos-Arapiuns",
  nome_sp = "Dasyprocta croconota"
)

cutia_tap_arap_quase_sem_repeticao
5.2.2.2.2 Plotando o histograma das frequĂȘncias de ocorrĂȘncia pela distĂąncia
cutia_tap_arap_quase_sem_repeticao |> 
  drop_na(distance) |> 
plotar_distribuicao_distancia_interativo(largura_caixa = 1)
5.2.2.2.3 Testando distĂąncia de truncamento (w)
5.2.2.2.3.1 Tabela com resumo comparativo dos modelos
# conduz a selecao da melhor distancia de truncamento a partir do ajsute de modelos com funcao de deteccao half-normal sem termos de ajuste
cutia_tap_arap_quase_sem_repeticao_dist_trunc <- cutia_tap_arap_quase_sem_repeticao |> 
  selecionar_distancia_truncamento()

cutia_tap_arap_quase_sem_repeticao_dist_trunc$selecao
5.2.2.2.3.2 Plotando o histograma com os dados truncados.
plotar_funcao_deteccao_selecao_distancia_truncamento(cutia_tap_arap_quase_sem_repeticao_dist_trunc)
5.2.2.2.4 Ajustando diferentes modelos de funçÔes de deteção
5.2.2.2.4.1 Uniforme + Cosseno
# ajustando a função de detecção uniforme para um truncamento de 10% dos dados
cutia_tap_arap_quase_sem_repeticao_unif <- cutia_tap_arap_quase_sem_repeticao |> 
  ajuste_modelos_distance_unif(truncamento = "10%")
5.2.2.2.4.2 Half-Normal sem termos de ajuste e com termos de ajuste
# ajustando a função de detecção half-normal para um truncamento de 10% dos dados
cutia_tap_arap_quase_sem_repeticao_hn <- cutia_tap_arap_quase_sem_repeticao |> 
  ajuste_modelos_distance_hn(truncamento = "10%")
5.2.2.2.4.3 Hazard-rate sem termos de ajuste e com termos de ajuste
# ajustando a função de detecção half-normal para um truncamento de 10% dos dados
cutia_tap_arap_quase_sem_repeticao_hr <- cutia_tap_arap_quase_sem_repeticao |> 
  ajuste_modelos_distance_hr(truncamento = "10%")
5.2.2.2.5 Comparando os modelos
5.2.2.2.5.1 Tabela com o resumo comparativo dos modelos
fluxo2_lista_modelos_ajustados <- list(
  `half-normal` = cutia_tap_arap_quase_sem_repeticao_hn, 
  `hazard-rate` = cutia_tap_arap_quase_sem_repeticao_hr, 
  `uniforme` = cutia_tap_arap_quase_sem_repeticao_unif
)

fluxo2_selecao_funcao_deteccao_termo_ajuste <- selecionar_funcao_deteccao_termo_ajuste(fluxo2_lista_modelos_ajustados)

fluxo2_selecao_funcao_deteccao_termo_ajuste
5.2.2.2.5.2 Gråficos de ajuste das funçÔes de deteção às probabilidades de deteção
# gerar uma lista com os modelos selecionados ordenados do melhor para o pior modelo
fluxo2_modelos_selecionados <- list(
  cutia_tap_arap_quase_sem_repeticao_hr$`Sem termo`,
  cutia_tap_arap_quase_sem_repeticao_hn$`Cosseno`,
  cutia_tap_arap_quase_sem_repeticao_unif$`Cosseno`,
  cutia_tap_arap_quase_sem_repeticao_unif$`Polinomial simples`,
  cutia_tap_arap_quase_sem_repeticao_hn$`Sem termo`
)

# atribuir o nome dos modelos aos itens da lista

names(fluxo2_modelos_selecionados) <- fluxo2_selecao_funcao_deteccao_termo_ajuste$Model

# plotar a probabilidade de detecção observada (barras) e a esperada (linhas e pontos)
plotar_funcao_deteccao_modelos_selecionados(fluxo2_modelos_selecionados)
5.2.2.2.5.3 Teste de bondade de ajuste dos modelos e Q-Q plots
bondade_ajuste_fluxo2 <- testar_bondade_ajuste(fluxo2_modelos_selecionados, plot = TRUE)
bondade_ajuste_fluxo2
5.2.2.2.6 Avaliando as estimativas de AbundĂąncia e Densidade
5.2.2.2.6.1 CaracterĂ­sticas da ĂĄrea de estudo e da taxa de encontro
# gera lista contendo os modelos selecionados para cada função de detecção e termo de ajuste
fluxo2_lista_modelos_ajustados_termos <- list(
  cutia_tap_arap_quase_sem_repeticao_hr$`Sem termo`,
  cutia_tap_arap_quase_sem_repeticao_hn$`Cosseno`,
  cutia_tap_arap_quase_sem_repeticao_unif$`Cosseno`,
  cutia_tap_arap_quase_sem_repeticao_unif$`Polinomial simples`,
  cutia_tap_arap_quase_sem_repeticao_hn$`Sem termo`
)

# ĂĄrea de estudo, tamanho da ĂĄrea de estudo, area coberta pelo esforço amostral, esforço amostral em metros, nĂșmero de detecçÔes, nĂșmero de transectos (ea), taxa de encontro, coeficiente de variação da taxa de encontro  
fluxo2_caracteristicas_area_estudo_taxa_encontro <- fluxo2_lista_modelos_ajustados_termos |> 
  gerar_caracteristicas_area_estudo_taxa_encontro(resultado_selecao_modelos = fluxo2_selecao_funcao_deteccao_termo_ajuste)

fluxo2_caracteristicas_area_estudo_taxa_encontro
5.2.2.2.6.2 Características de abundùncia, esforço e detecção
# ĂĄrea de estudo, tamanho da ĂĄrea de estudo, trilhas ou estaçÔes amostrais, esforço total em cada trilha, abundĂąncia estimada em cada estação amostral, nĂșmero de detecçÔes em cada estação amostral, ĂĄrea total amostrada
fluxo2_caracteristicas_esforco_abundancia_deteccao <- fluxo2_lista_modelos_ajustados_termos |> 
  gerar_caracteristicas_esforco_abundancia_deteccao(resultado_selecao_modelos = fluxo2_selecao_funcao_deteccao_termo_ajuste)

fluxo2_caracteristicas_esforco_abundancia_deteccao
5.2.2.2.6.3 CaracterĂ­sticas de densidade
# total, densidade estimada, erro padrão da densidade destimada, coeficiente de variação da densidade destimada, intervalo de confiança inferior e superior do coeficiente de variação, gruas de liberdade
fluxo2_caracteristicas_densidade <- fluxo2_lista_modelos_ajustados_termos |> 
  gerar_caracteristicas_densidade(resultado_selecao_modelos = fluxo2_selecao_funcao_deteccao_termo_ajuste)

fluxo2_caracteristicas_densidade

5.2.2.3 Fluxo 3 - Distùncias agrupadas com todas as repetiçÔes

Aqui vamos partir do mesmo conjunto de dados do Fluxo 1 (cutia_tap_arap), com todas as repetiçÔes, mas vamos agrupar as distùncias em intervalos. Vamos usar o mesmo valor de truncamento, removendo 10% das observaçÔes nas maiores distùncias, o que significa que aproveitaremos as observaçÔes feitas até 15m de distùncia do observador.

5.2.2.3.1 Plotando o histograma das frequĂȘncias de ocorrĂȘncia pela distĂąncia

O histograma interativo estĂĄ disponĂ­vel no app em Shiny app_distancia_interativo.R.

Aqui, plotamos quatro histogramas com binagens diferentes, para observar o efeito de agrupar os dados sobre as distribuiçÔes das frequĂȘncias de ocorrĂȘncia nos histogramas.

cutia_tap_arap |> 
  drop_na(distance) |> 
plotar_distribuicao_distancia_interativo(largura_caixa = 1)

cutia_tap_arap |> 
  drop_na(distance) |> 
plotar_distribuicao_distancia_interativo(largura_caixa = 2)

cutia_tap_arap |> 
  drop_na(distance) |> 
plotar_distribuicao_distancia_interativo(largura_caixa = 3)

cutia_tap_arap |> 
  drop_na(distance) |> 
plotar_distribuicao_distancia_interativo(largura_caixa = 5)
5.2.2.3.2 Definindo os intevalos de distĂąncia de agrupamento
5.2.2.3.2.1 Primeira binagem - Intervalos iguais de 1.5m
cutia_tap_arap_bin1 <- create_bins(
  cutia_tap_arap[!is.na(cutia_tap_arap$distance),], 
  c(0, 1.5, 3, 4.5, 6, 7.5, 9, 10.5, 12, 13.5, 15)
)
5.2.2.3.2.2 Segunda binagem - Primeiro intervalo de 1m e demais intervalos de 1.4m
cutia_tap_arap_bin2 <- create_bins(
  cutia_tap_arap[!is.na(cutia_tap_arap$distance),], 
  c(0, 1, 2.4, 3.8, 5.2, 6.6, 8, 9.4, 10.8, 12.2, 13.6, 15)
)
5.2.2.3.2.3 Terceira binagem - Intervalos iguais de 2.5m
cutia_tap_arap_bin3 <- create_bins(
  cutia_tap_arap[!is.na(cutia_tap_arap$distance),], 
  c(0, 2.5, 5, 7.5, 10, 12.5, 15)
)
5.2.2.3.3 Ajustando diferentes modelos de funçÔes de deteção
5.2.2.3.3.1 Uniforme + Cosseno

Primeira Binagem


cutia_tap_arap_bin1_unif <- cutia_tap_arap_bin1 |> 
  ajuste_modelos_distance_unif(truncamento = 15)

Segunda binagem


cutia_tap_arap_bin2_unif <- cutia_tap_arap_bin2 |> 
  ajuste_modelos_distance_unif(truncamento = 15)

Terceira binagem


cutia_tap_arap_bin3_unif <- cutia_tap_arap_bin3 |> 
  ajuste_modelos_distance_unif(truncamento = 15)
5.2.2.3.3.2 Half-Normal sem termos de ajuste e com termos de ajuste

Primeira binagem


cutia_tap_arap_bin1_hn <- cutia_tap_arap_bin1 |> 
  ajuste_modelos_distance_hn(truncamento = 15)

Segunda binagem


cutia_tap_arap_bin2_hn <- cutia_tap_arap_bin2 |> 
  ajuste_modelos_distance_hn(truncamento = 15)

Terceira binagem


cutia_tap_arap_bin3_hn <- cutia_tap_arap_bin3 |> 
  ajuste_modelos_distance_hn(truncamento = 15)
5.2.2.3.3.3 Hazard-rate sem termos de ajuste e com termos de ajuste

Primeira binagem


cutia_tap_arap_bin1_hr <- cutia_tap_arap_bin1 |> 
  ajuste_modelos_distance_hr(truncamento = 15)

Segunda binagem


cutia_tap_arap_bin2_hr <- cutia_tap_arap_bin2 |> 
  ajuste_modelos_distance_hr(truncamento = 15)

Terceira binagem


cutia_tap_arap_bin3_hr <- cutia_tap_arap_bin3 |> 
  ajuste_modelos_distance_hr(truncamento = 15)
5.2.2.3.4 Comparando os modelos
5.2.2.3.4.1 Tabela com o resumo comparativo dos modelos
fluxo3.1_lista_modelos_ajustados <- list(
  `half-normal` = cutia_tap_arap_bin1_hn, 
  `hazard-rate` = cutia_tap_arap_bin1_hr, 
  `uniforme` = cutia_tap_arap_bin1_unif
)

fluxo3.1_selecao_funcao_deteccao_termo_ajuste <- selecionar_funcao_deteccao_termo_ajuste(fluxo3.1_lista_modelos_ajustados)

fluxo3.1_selecao_funcao_deteccao_termo_ajuste
fluxo3.2_lista_modelos_ajustados <- list(
  `half-normal` = cutia_tap_arap_bin2_hn, 
  `hazard-rate` = cutia_tap_arap_bin2_hr, 
  `uniforme` = cutia_tap_arap_bin2_unif
)

fluxo3.2_selecao_funcao_deteccao_termo_ajuste <- selecionar_funcao_deteccao_termo_ajuste(fluxo3.2_lista_modelos_ajustados)

fluxo3.2_selecao_funcao_deteccao_termo_ajuste
fluxo3.3_lista_modelos_ajustados <- list(
  `half-normal` = cutia_tap_arap_bin3_hn, 
  `hazard-rate` = cutia_tap_arap_bin3_hr, 
  `uniforme` = cutia_tap_arap_bin3_unif
)

fluxo3.3_selecao_funcao_deteccao_termo_ajuste <- selecionar_funcao_deteccao_termo_ajuste(fluxo3.3_lista_modelos_ajustados)

fluxo3.3_selecao_funcao_deteccao_termo_ajuste
5.2.2.3.4.2 Gråficos de ajuste das funçÔes de deteção às probabilidades de deteção

Primeira binagem

fluxo3.1_modelos_selecionados <- list(
  cutia_tap_arap_bin1_hn$`Cosseno`,
  cutia_tap_arap_bin1_unif$`Cosseno`,
  cutia_tap_arap_bin1_hr$`Sem termo`,
  cutia_tap_arap_bin1_unif$`Polinomial simples`,
  cutia_tap_arap_bin1_hn$`Sem termo`
)

plotar_funcao_deteccao_modelos_selecionados(fluxo3.1_modelos_selecionados)

Segunda binagem

fluxo3.2_modelos_selecionados <- list(
  cutia_tap_arap_bin2_hn$`Cosseno`,
  cutia_tap_arap_bin2_hr$`Sem termo`,
  cutia_tap_arap_bin2_unif$`Cosseno`,
  cutia_tap_arap_bin2_unif$`Polinomial simples`,
  cutia_tap_arap_bin2_hn$`Sem termo`
)

plotar_funcao_deteccao_modelos_selecionados(fluxo3.2_modelos_selecionados)

Terceira binagem

fluxo3.3_modelos_selecionados <- list(
  cutia_tap_arap_bin3_hn$`Cosseno`,
  cutia_tap_arap_bin3_hr$`Cosseno`,
  cutia_tap_arap_bin3_hr$`Polinomial simples`,
  cutia_tap_arap_bin3_hr$`Sem termo`,
  cutia_tap_arap_bin3_unif$`Cosseno`,
  cutia_tap_arap_bin3_unif$`Polinomial simples`,
  cutia_tap_arap_bin3_hn$`Sem termo`
)

plotar_funcao_deteccao_modelos_selecionados(fluxo3.3_modelos_selecionados)
5.2.2.3.4.3 Teste de bondade de ajuste dos modelos e Q-Q plots

Ainda estamos ajustando os outputs para os testes de bondade, pois a binagem um conflito com o formato de tabela definido pela função original.

Primeira binagem

Segunda binagem

Terceira binagem

5.2.2.3.5 Avaliando as estimativas de AbundĂąncia e Densidade
5.2.2.3.5.1 CaracterĂ­sticas da ĂĄrea de estudo e da taxa de encontro

Primeira binagem

# gera lista contendo os modelos selecionados para cada função de detecção e termo de ajuste
fluxo3.1_lista_modelos_ajustados_termos <- list(
  cutia_tap_arap_bin1_hn$`Cosseno`,
  cutia_tap_arap_bin1_unif$`Cosseno`,
  cutia_tap_arap_bin1_hr$`Sem termo`,
  cutia_tap_arap_bin1_unif$`Polinomial simples`,
  cutia_tap_arap_bin1_hn$`Sem termo`
)

# ĂĄrea de estudo, tamanho da ĂĄrea de estudo, area coberta pelo esforço amostral, esforço amostral em metros, nĂșmero de detecçÔes, nĂșmero de transectos (ea), taxa de encontro, coeficiente de variação da taxa de encontro  
fluxo3.1_caracteristicas_area_estudo_taxa_encontro <- fluxo3.1_lista_modelos_ajustados_termos |> 
  gerar_caracteristicas_area_estudo_taxa_encontro(resultado_selecao_modelos = fluxo3.1_selecao_funcao_deteccao_termo_ajuste)

fluxo3.1_caracteristicas_area_estudo_taxa_encontro

Segunda binagem

# gera lista contendo os modelos selecionados para cada função de detecção e termo de ajuste
fluxo3.2_lista_modelos_ajustados_termos <- list(
  cutia_tap_arap_bin2_hn$`Cosseno`,
  cutia_tap_arap_bin2_hr$`Sem termo`,
  cutia_tap_arap_bin2_unif$`Cosseno`,
  cutia_tap_arap_bin2_unif$`Polinomial simples`,
  cutia_tap_arap_bin2_hn$`Sem termo`
)

# ĂĄrea de estudo, tamanho da ĂĄrea de estudo, area coberta pelo esforço amostral, esforço amostral em metros, nĂșmero de detecçÔes, nĂșmero de transectos (ea), taxa de encontro, coeficiente de variação da taxa de encontro  
fluxo3.2_caracteristicas_area_estudo_taxa_encontro <- fluxo3.2_lista_modelos_ajustados_termos |> 
  gerar_caracteristicas_area_estudo_taxa_encontro(resultado_selecao_modelos = fluxo3.2_selecao_funcao_deteccao_termo_ajuste)

fluxo3.2_caracteristicas_area_estudo_taxa_encontro

Terceira binagem

# gera lista contendo os modelos selecionados para cada função de detecção e termo de ajuste
fluxo3.3_lista_modelos_ajustados_termos <- list(
  cutia_tap_arap_bin3_hn$`Cosseno`,
  cutia_tap_arap_bin3_hr$`Cosseno`,
  cutia_tap_arap_bin3_hr$`Polinomial simples`,
  cutia_tap_arap_bin3_hr$`Sem termo`,
  cutia_tap_arap_bin3_unif$`Cosseno`,
  cutia_tap_arap_bin3_unif$`Polinomial simples`,
  cutia_tap_arap_bin3_hn$`Sem termo`
)

# ĂĄrea de estudo, tamanho da ĂĄrea de estudo, area coberta pelo esforço amostral, esforço amostral em metros, nĂșmero de detecçÔes, nĂșmero de transectos (ea), taxa de encontro, coeficiente de variação da taxa de encontro  
fluxo3.3_caracteristicas_area_estudo_taxa_encontro <- fluxo3.3_lista_modelos_ajustados_termos |> 
  gerar_caracteristicas_area_estudo_taxa_encontro(resultado_selecao_modelos = fluxo3.3_selecao_funcao_deteccao_termo_ajuste)

fluxo3.3_caracteristicas_area_estudo_taxa_encontro
5.2.2.3.5.2 Características de abundùncia, esforço e detecção

Primeira binagem

# ĂĄrea de estudo, tamanho da ĂĄrea de estudo, trilhas ou estaçÔes amostrais, esforço total em cada trilha, abundĂąncia estimada em cada estação amostral, nĂșmero de detecçÔes em cada estação amostral, ĂĄrea total amostrada
fluxo3.1_caracteristicas_esforco_abundancia_deteccao <- fluxo3.1_lista_modelos_ajustados_termos |> 
  gerar_caracteristicas_esforco_abundancia_deteccao(resultado_selecao_modelos = fluxo3.1_selecao_funcao_deteccao_termo_ajuste)

fluxo3.1_caracteristicas_esforco_abundancia_deteccao

Segunda binagem

# ĂĄrea de estudo, tamanho da ĂĄrea de estudo, trilhas ou estaçÔes amostrais, esforço total em cada trilha, abundĂąncia estimada em cada estação amostral, nĂșmero de detecçÔes em cada estação amostral, ĂĄrea total amostrada
fluxo3.2_caracteristicas_esforco_abundancia_deteccao <- fluxo3.2_lista_modelos_ajustados_termos |> 
  gerar_caracteristicas_esforco_abundancia_deteccao(resultado_selecao_modelos = fluxo3.2_selecao_funcao_deteccao_termo_ajuste)

fluxo3.2_caracteristicas_esforco_abundancia_deteccao

Terceira binagem

# ĂĄrea de estudo, tamanho da ĂĄrea de estudo, trilhas ou estaçÔes amostrais, esforço total em cada trilha, abundĂąncia estimada em cada estação amostral, nĂșmero de detecçÔes em cada estação amostral, ĂĄrea total amostrada
fluxo3.3_caracteristicas_esforco_abundancia_deteccao <- fluxo3.3_lista_modelos_ajustados_termos |> 
  gerar_caracteristicas_esforco_abundancia_deteccao(resultado_selecao_modelos = fluxo3.3_selecao_funcao_deteccao_termo_ajuste)

fluxo3.3_caracteristicas_esforco_abundancia_deteccao
5.2.2.3.5.3 CaracterĂ­sticas de densidade

Primeira binagem

# total, densidade estimada, erro padrão da densidade destimada, coeficiente de variação da densidade destimada, intervalo de confiança inferior e superior do coeficiente de variação, gruas de liberdade
fluxo3.1_caracteristicas_densidade <- fluxo3.1_lista_modelos_ajustados_termos |> 
  gerar_caracteristicas_densidade(resultado_selecao_modelos = fluxo3.1_selecao_funcao_deteccao_termo_ajuste)

fluxo3.1_caracteristicas_densidade

Segunda binagem

# total, densidade estimada, erro padrão da densidade destimada, coeficiente de variação da densidade destimada, intervalo de confiança inferior e superior do coeficiente de variação, gruas de liberdade
fluxo3.2_caracteristicas_densidade <- fluxo3.2_lista_modelos_ajustados_termos |> 
  gerar_caracteristicas_densidade(resultado_selecao_modelos = fluxo3.2_selecao_funcao_deteccao_termo_ajuste)

fluxo3.2_caracteristicas_densidade

Terceira binagem

# total, densidade estimada, erro padrão da densidade destimada, coeficiente de variação da densidade destimada, intervalo de confiança inferior e superior do coeficiente de variação, gruas de liberdade
fluxo3.3_caracteristicas_densidade <- fluxo3.3_lista_modelos_ajustados_termos |> 
  gerar_caracteristicas_densidade(resultado_selecao_modelos = fluxo3.3_selecao_funcao_deteccao_termo_ajuste)

fluxo3.3_caracteristicas_densidade

5.2.3 Amostragem por DistĂąncia com MĂșltiplas CovariĂĄveis

Aqui, vamos usar a abordagem do Fluxo 2, com amostragens reduzidas, para o ajuste de covariĂĄveis. Vamos usar o tamanho do grupo como covariĂĄvel.

5.2.3.0.1 Ajustando diferentes modelos com covariĂĄveis

Para o uso de coveriåveis, podemos usar somente as distribuiçÔes half-normal ou hazard-rate, pois ambas possuem o parùmetro escalar pelo qual o vetor das covariåveis serå multiplicado. Não é recomendåvel o uso de termos de ajuste com o uso de covariåveis pela grande chance de perda de monotonicidade nas curvas das funçÔes de detecção. Assim, vamos trabalhar com as seguintes combinaçÔes de modelos

5.2.3.0.1.1 Half-normal sem termos de ajuste (HN)
# ajustando a função de detecção half-normal para um truncamento de 10% dos dados
cutia_cov_hn <- cutia_tap_arap_quase_sem_repeticao |> 
  ajuste_modelos_distance_hn(lista_termos_ajuste = list(`Sem termo`= NULL),truncamento = "10%")

lista_termos_ajuste = list(Sem termo) = NULL),

5.2.3.0.1.2 HN + Tamanho do grupo (HN + S)
# ajustando a função de detecção half-normal para um truncamento de 10% dos dados
cutia_cov_hn_s <- cutia_tap_arap_quase_sem_repeticao |> 
  ajuste_modelos_distance_hn(lista_termos_ajuste = list(`Sem termo`= NULL),truncamento = "10%", formula = ~size)
5.2.3.0.1.3 Hazard-rate sem termos de ajuste (HZ)
# ajustando a função de detecção half-normal para um truncamento de 10% dos dados
cutia_cov_hr <- cutia_tap_arap_quase_sem_repeticao |> 
  ajuste_modelos_distance_hr(lista_termos_ajuste = list(`Sem termo`= NULL),truncamento = "10%")
5.2.3.0.1.4 HZ + Tamanho do grupo (HZ + S)
# ajustando a função de detecção half-normal para um truncamento de 10% dos dados
cutia_cov_hr_s <- cutia_tap_arap_quase_sem_repeticao |> 
  ajuste_modelos_distance_hr(lista_termos_ajuste = list(`Sem termo`= NULL),truncamento = "10%", formula = ~size)
5.2.3.0.2 Comparando os modelos
5.2.3.0.2.1 Tabela com o resumo comparativo dos modelos

Ainda estamos ajustando a função para poder gerar a tabela com o resumo dos resultados. A função criada para gerar tabela ainda não comporta os dados de modelos com covariåveis.

5.2.3.0.2.2 Gråficos de ajuste das funçÔes de deteção às probabilidades de deteção

Ainda estamos ajustando a função para poder gerar os gråficos dos modelos com covariåveis. A função criada para os gråficos ainda não comporta os dados de modelos com covariåveis.

cov_modelos_selecionados <- list(
  cutia_cov_hn$`Sem termo`,
  cutia_cov_hr$`Sem termo`
)

plotar_funcao_deteccao_modelos_selecionados(cov_modelos_selecionados)
5.2.3.0.2.3 Teste de bondade de ajuste dos modelos e Q-Q plots

Ainda estamos ajustando a função para poder gerar a tabela com os resultados do Cramér-von Mises e os gråficos dos modelos com covariåveis. A função criada para gerar tabela e os Q-Q plots ainda não comporta os dados de modelos com covariåveis.

bondade_ajuste_cov <- testar_bondade_ajuste(cov_modelos_selecionados, plot = TRUE)
bondade_ajuste_cov
5.2.3.0.3 Avaliando as estimativas de AbundĂąncia e Densidade

Para o uso de covariåveis, as estimativas de abundùncia/densidade devem ser feitas através do bootstrap (função bootdht do Distance). Ainda estamos implementando o bootstrap em nosso fluxo de estimativas de taxa de encontro, abundùncia e densidade.

LS0tCnRpdGxlOiAiRmx1eG8gZGUgdHJhYmFsaG86IGRlIHByb2R1Y2FvIGRvcyBjb2RpZ29zIGRvcyBkYWRvcyBkZSBBbW9zdHJhZ2VtIHBvciBEaXN0YW5jaWEKICAtIFByb2dyYW1hIE1vbml0b3JhIElDTUJpby9NTUEiCmF1dGhvcjogIkx1Y2lhbmEgRnVzaW5hdHRvIFxuIFZpdG9yIEJvcmdlcy1Kw7puaW9yIgpkYXRlOiBDcmlhZG8gZW0gMzEgZGUgbWFyw6dvIGRlIDIwMjMsIGF0dWFsaXphZG8gZW0gYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCBkZSAlQgogIGRlICVZJylgCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogNQogICAgdG9jX2Zsb2F0OiBubwogICAgbnVtYmVyX3NlY3Rpb246IHllcwogICAgY29kZV9mb2xkaW5nOiBzaG93CmVkaXRvcl9vcHRpb25zOgogIG1hcmtkb3duOgogICAgd3JhcDogNzIKLS0tCgojICoqUEFSVEUgSSAtLSBDdWlkYWRvcyBhbnRlcyBkZSBjb21lw6dhciBhIHJvZGFyIG9zIGPDs2RpZ29zIG5vIFIqKgoKUGFyYSBxdWUgbyBhcnF1aXZvIGBmbHV4b19kZV90cmFiYWxob19jb2RpZ29zX2ludGVyYXRpdm9fZmluYWwuUm1kYCBmdW5jaW9uZSBkZSBtYW5laXJhIGFkZXF1YWRhIGVtIHN1YSBtw6FxdWluYSwgdm9jw6ogZGV2ZSBkZXNjb21wYWN0YXIgbyBhcnF1aXZvIGBwaXBlcjNEX21vbml0b3JhX2Zsb3Jlc3RhbC56aXBgLiBVbWEgbm92YSBwYXN0YSBjb20gbyBtZXNtbyBub21lIHNlcsOhIGNyaWFkYSBubyBkaXJldMOzcmlvIGVzY29saGlkbyBwYXJhIGV4ZWN1dGFyIGEgZGVzY29tcGFjdGHDp8Ojby4gTmVsYSwgdm9jw6ogZGV2ZXLDoSBjbGljYXIgZHVhcyB2ZXplcyBzb2JyZSBvIMOtY29uZSBgTW9uaXRvcmEuUnByb2pgIHBhcmEgY29tZcOnYXIgYSBleGVjdXRhciBvcyBhcnF1aXZvcyBjb250aWRvcyBubyBwcm9qZXRvLiBBbyByZWFsaXphciBlc3NlIHByb2NlZGltZW50bywgdm9jw6ogZ2FyYW50aXLDoSBxdWUgc2V1IGRpcmV0w7NyaW8gZGUgdHJhYmFsaG8gZXN0ZWphIGNvbmZpZ3VyYWRvIGNvbW8gbyBkaXJldMOzcmlvIGRhIHBhc3RhIGBwaXBlcjNkX21vbml0b3JhX2Zsb3Jlc3RhbGAgYXNzZWd1cmFuZG8gbyBmdW5jaW9uYW1lbnRvIGNvcnJldG8gZG9zIGPDs2RpZ29zIGNvbnRpZG9zIG5vIHByb2pldG8uCgojIyBDYXJyZWdhbmRvIGFzIGZ1bsOnw7VlcwoKYGBge3IgY29uZmlndXJhw6fDo28sIGluY2x1ZGU9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkoRGlzdGFuY2UpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoRFQpCmxpYnJhcnkoZm9yY2F0cykKbGlicmFyeShnZ3B1YnIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShoZXJlKQpsaWJyYXJ5KGx1YnJpZGF0ZSkKbGlicmFyeShtcmRzKQpsaWJyYXJ5KHBsb3RseSkKbGlicmFyeShwdXJycikKbGlicmFyeShyZWFkcikKbGlicmFyeShyZWFkeGwpCmxpYnJhcnkoc3RyaW5naSkKbGlicmFyeShzdHJpbmdyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KHRpZHlzZWxlY3QpCnNvdXJjZShwYXN0ZTAoaGVyZTo6aGVyZSgpLCAiL1IvbWluaGFzX2Z1bmNvZXMuUiIpKQoKYGBgCgojIyAqKlJzdHVkaW8vUGFjb3Rlcy92ZXJzw7Vlcy9zaXN0ZW1hcyBvcGVyYWNpb25haXMqKgoKQSB0YWJlbGEgYXNlZ3VpciDDqSB1bWEgcmVmZXLDqm5jaWEgcGFyYSBhcyB2ZXJzw7VlcyBkb3MgcGFjb3RlcyB1dGlsaXphZG9zIG5vIG5lc3NlIHByb2pldG8uIFBhcmEgZ2FyYW50aXIgYSByZXByb2R1w6fDo28gZG9zIGPDs2RpZ29zLCDDqSBpbXBvcnRhbnRlIHF1ZSBvIFIgZSBvcyBwYWNvdGVzIHVzYWRvcyBubyBwcm9qZXRvIGFwcmVzZW50ZW0gYXMgY29uZmlndXJhw6fDtWVzIG3DrW5pbWFzIGNvbnRpZGFzIG5hIHRhYmVsYSAxLgoKYGBge3J9CiMgZ2VyYXIgaW5mb3JtYcOnw7VlcyBzb2JyZSBvcyBwYWNvdGVzIGNhcnJlZ2Fkb3MKaW5mbyA8LSBzZXNzaW9uSW5mbygpCgojIGdlcmFyIHRhYmVsYSBjb20gb3MgcGFjb3RlcyBlIHZlcnPDtWVzCnRyaWJibGUoCiAgflBhY290ZXMsICAgICAgICAgICAgICAgICAgICAgICAgIH5WZXJzw6NvLAogIHZlcnNpb24kbGFuZ3VhZ2UsICAgICAgICAgICAgICAgICB2ZXJzaW9uJHZlcnNpb24uc3RyaW5nLAogIGluZm8kb3RoZXJQa2dzJGRwbHlyJFBhY2thZ2UsICAgICBpbmZvJG90aGVyUGtncyRkcGx5ciRWZXJzaW9uLAogIGluZm8kb3RoZXJQa2dzJERpc3RhbmNlJFBhY2thZ2UsICBpbmZvJG90aGVyUGtncyREaXN0YW5jZSRWZXJzaW9uLAogIGluZm8kb3RoZXJQa2dzJERUJFBhY2thZ2UsICAgICAgICBpbmZvJG90aGVyUGtncyREVCRWZXJzaW9uLAogIGluZm8kb3RoZXJQa2dzJGZvcmNhdHMkUGFja2FnZSwgICAgICAgIGluZm8kb3RoZXJQa2dzJGZvcmNhdHMkVmVyc2lvbiwKICBpbmZvJG90aGVyUGtncyRmbGV4dGFibGUkUGFja2FnZSwgaW5mbyRvdGhlclBrZ3MkZmxleHRhYmxlJFZlcnNpb24sCiAgaW5mbyRvdGhlclBrZ3MkZ2dwbG90MiRQYWNrYWdlLCAgICAgaW5mbyRvdGhlclBrZ3MkZ2dwbG90MiRWZXJzaW9uLAogIGluZm8kb3RoZXJQa2dzJGdncHViciRQYWNrYWdlLCAgICAgaW5mbyRvdGhlclBrZ3MkZ2dwdWJyJFZlcnNpb24sCiAgaW5mbyRvdGhlclBrZ3MkaGVyZSRQYWNrYWdlLCAgICAgaW5mbyRvdGhlclBrZ3MkaGVyZSRWZXJzaW9uLAogIGluZm8kb3RoZXJQa2dzJGx1YnJpZGF0ZSRQYWNrYWdlLCBpbmZvJG90aGVyUGtncyRsdWJyaWRhdGUkVmVyc2lvbiwKICBpbmZvJG90aGVyUGtncyRtcmRzJFBhY2thZ2UsICAgICBpbmZvJG90aGVyUGtncyRtcmRzJFZlcnNpb24sCiAgaW5mbyRvdGhlclBrZ3MkcGxvdGx5JFBhY2thZ2UsICAgIGluZm8kb3RoZXJQa2dzJHBsb3RseSRWZXJzaW9uLAogIGluZm8kb3RoZXJQa2dzJHB1cnJyJFBhY2thZ2UsICAgICBpbmZvJG90aGVyUGtncyRwdXJyciRWZXJzaW9uLAogIGluZm8kb3RoZXJQa2dzJHJlYWRyJFBhY2thZ2UsICAgICBpbmZvJG90aGVyUGtncyRyZWFkciRWZXJzaW9uLAogIGluZm8kb3RoZXJQa2dzJHJlYWR4bCRQYWNrYWdlLCAgICAgaW5mbyRvdGhlclBrZ3MkcmVhZHhsJFZlcnNpb24sCiAgaW5mbyRvdGhlclBrZ3Mkc3RyaW5naSRQYWNrYWdlLCAgICAgaW5mbyRvdGhlclBrZ3Mkc3RyaW5naSRWZXJzaW9uLAogIGluZm8kb3RoZXJQa2dzJHN0cmluZ3IkUGFja2FnZSwgICAgIGluZm8kb3RoZXJQa2dzJHN0cmluZ3IkVmVyc2lvbiwKICBpbmZvJG90aGVyUGtncyR0aWJibGUkUGFja2FnZSwgICAgaW5mbyRvdGhlclBrZ3MkdGliYmxlJFZlcnNpb24sCiAgaW5mbyRvdGhlclBrZ3MkdGlkeXIkUGFja2FnZSwgICAgIGluZm8kb3RoZXJQa2dzJHRpZHlyJFZlcnNpb24sCiAgaW5mbyRvdGhlclBrZ3MkdGlkeXNlbGVjdCRQYWNrYWdlLGluZm8kb3RoZXJQa2dzJHRpZHlzZWxlY3QkVmVyc2lvbgopIHw+IAogIGZsZXh0YWJsZTo6cWZsZXh0YWJsZSgpIHw+IAogIGZsZXh0YWJsZTo6c2V0X2NhcHRpb24oCiAgICAiVGFiZWxhIDEgLSBjb25maWd1cmHDp8OjbyBkZSBwYWNvdGVzIG5lY2Vzc8OhcmlvcyBlIHJlc3BlY3RpdmFzIHZlcnPDtWVzIG3DrW5pbWFzIHF1ZSBkZXZlbSBzZXIgdXRpbGl6YWRhcyBwYXJhIHJlcHJvZHV6aXIgb3MgY8OzZGlnb3MiCiAgKQpgYGAKCiMjICoqQ3VpZGFkb3MgY29tIGEgcGxhbmlsaGEgLnhsc3ggcXVlIHNlcsOhIGltcG9ydGFkYSAocGFyYSBxdWUgbWFudGVuaGEgbyBwYWRyw6NvIGRhIHBsYW5pbGhhIGRlIHJlZmVyw6puY2lhIGRvIElDTUJpbykqKgoKQSBwcmltZWlyYSBmdW7Dp8OjbyB1dGxpemFkYSwgYGNhcnJlZ2FyX2RhZG9zX2JydXRvc194bHN4KClgLCBpcsOhCmNhcnJlZ2FyIGEgcGxhbmlsaGEgZW0gZm9ybWF0byBleGNlbCwKYFBsYW5pbGhhIE9maWNpYWwgY29uc29saWRhZGEgZGUgTWFzdG8tYXZlcyAyMDE0LTIxIFZhbGlkYWRhIENFTUFWRSBDUEIgQ0VOQVAueGxzeGAsCmUgZ2VyYSBhdXRvbWF0aWNhbWVudGUgbyBhcnF1aXZvIGBkYWRvc19icnV0b3MucmRzYCBuYSBwYXN0YQpgZGF0YS1yYXdgLiBBIGZ1bsOnw6NvIHNlZ3VpbnRlIGEgc2VyIHV0aWxpemFkYSwgYGNhcnJlZ2FyX2RhZG9zX2NvbXBsZXRvcygpYCBxdWUgaXLDoSBjYXJyZWdhciBvIGFycXVpdm8KYGRhZG9zX2JydXRvcy5yZHNgLiBFc3NhIGZ1bsOnw6NvIGZvaSBlc2NyaXRhIHBhcmEgY2FycmVnYSBvcyBkYWRvcyBlCm9wZXJhciB1bWEgc8OpcmllIGRlIHRyYW5zZm9ybWHDp8O1ZXMgcGFyYSBkZXZvbHbDqi1sbyBubyBmb3JtYXRvCnBhZHJvbml6YWRvIGRvIHByb2dyYW1hICoqRElTVEFOQ0UqKiBwYXJhIFdpbmRvd3MuIFBvcnRhbnRvLCBwYXJhCmdhcmFudGlyIGEgcmVwcm9kdXRpYmlsaWRhZGUgZG9zIGPDs2RpZ29zIHByb2R1emlkb3MgZW0gdmVyc8O1ZXMKYXR1YWxpemFkYXMgZGEgYmFzZSBkZSBkYWRvcyBkbyBNb25pdG9yYSwgw6kgaW1wb3J0YW50ZSB0b21hciBhbGd1bnMKY3VpZGFkb3MuCgpPIHByaW1laXJvIGUgbWFpcyBpbXBvcnRhbnRlIGN1aWRhZG8gw6kgKiptYW50ZXIgYSBjb25zaXN0w6puY2lhIGRvcyBub21lcyBkYXMgY29sdW5hcyoqIGVtIHZlcnPDtWVzIGF0dWFsaXphZGFzIGRhIGJhc2UgZGUgZGFkb3MgZG8gTW9uaXRvcmEuIEFsw6ltIGRlIGNhcnJlZ2FyIG9zIGRhZG9zLCBhIGZ1bsOnw6NvIGBjYXJyZWdhcl9kYWRvc19jb21wbGV0b3MoKWAgYXBsaWNhIHVtYSBzw6lyaWUgZGUgdHJhbnNmb3JtYcOnw7VlcyBuYXMgY29sdW5hcy4gU2V1cyBub21lcyBzw6NvIGFsdGVyYWRvcywgZSBhIGVzc2FzIHPDo28gYXRyaWJ1w61kb3MgdGlwb3MgYXByb3ByaWFkb3MgKGRhdGEsIGNhcmFjdGVyLCBmYXRvciwgaW50ZWlybyBlIG51bcOpcmljbyksIGxpbmhhcyBzw6NvIGVsaW1pbmFkYXMgZSBub3ZhcyBjb2x1bmFzIHPDo28gZ2VyZWFkYXMuIFBhcmEKZXhlbXBsaWZpY2FyLCB2ZWphIG8gY8OzZGlnbyBhYmFpeG8uIEVsZSBmb2kgZXNjcml0byBwYXJhIGV4ZWN1dGFyIGFzCnByaW1laXJhcyB0cmFuc2Zvcm1hw6fDtWVzIG5vcyBkYWRvcyBlIGNvbnN0aXR1aSBvIGNvcnBvIGRhIGZ1bsOnw6NvCmBjYXJyZWdhcl9kYWRvc19maWx0cmFkb3MoKWAuCgpgYGB7cn0KIyBjYXJyZWdhciBhIGJhc2UgZGUgZGFkb3MgZG8gTW9uaXRvcmEKZGFkb3NfYnJ1dG9zIDwtIGNhcnJlZ2FyX2RhZG9zX2JydXRvc194bHN4KCkKCiMgZ2VyYXIgbyBkYXRhLmZyYW1lIGRlc2VqYWRvIHJlcHJvZHV6aW5kbyBhcyB0cmFuc2Zvcm1hw6fDtWVzIHJlYWxpemFkYXMgcGVsYSBmdW7Dp8OjbyBjYXJyZWdhcl9kYWRvc19jb21wbGV0b3MoKQpkYWRvc19maWx0cmFkb3MgPC0gZGFkb3NfYnJ1dG9zIHw+ICAKICAjIHNlbGVjaW9uYXIgYXMgY29sdW5hcyBuZWNlc3PDoXJpYXMgcGFyYSBhcyBhbmFsaXNlcywgcGFkcm9uaXphbmRvIG9zIG5vbWVzIHBhcmEgbyBmb3JtYXRvIERJU1RBTkNFCiAgZHBseXI6OnNlbGVjdCgKICAgIHVjX2NvZGUgPSBDRFVDLAogICAgdWNfbmFtZSA9IGBMb2NhbCAtIE5vbWUgZGEgVW5pZGFkZSBkZSBDb25zZXJ2YWNhb2AsCiAgICBlYV9udW1iZXIgPSBgTnVtZXJvIGRhIEVzdGFjYW8gQW1vc3RyYWxgLAogICAgZWFfbmFtZSA9IGBOb21lIGRhIEVBYCwKICAgIHNlYXNvbiA9IGBFc3RhY2FvIGRvIGFub2AsCiAgICBzYW1wbGluZ19kYXkgPSBgZGF0YSBkYSBhbW9zdHJhZ2VtYCwKICAgIGRheV9lZmZvcnQgPSBgRXNmb3JjbyBkZSBhbW9zdHJhZ2VtIHRhbWFuaG8gZGEgdHJpbGhhIChtKWAsCiAgICBzcCA9IGBFc3BlY2llcyB2YWxpZGFkYXMgcGFyYSBhbmFsaXNlIGRvIElDTUJpb2AsCiAgICBkaXN0YW5jZSA9IGBkaXN0YW5jaWEgKG0pICAgICBkbyBhbmltYWwgZW0gcmVsYWNhbyBhIHRyaWxoYWAsCiAgICBncm91cF9zaXplID0gYG4gZGUgYW5pbWFpc2AsCiAgICBvYnNlcnZhZG9yZXMgPSBgbm9tZSBkb3Mgb2JzZXJ2YWRvcmVzYAogICkgfD4KICAjIGF0cmlidWlyIG9zIHRpcG9zIGNvcnJldG9zIMOgcyBjb2x1bmFzIGUgY3JpYXIgbm92YXMgY29sdW5hcwogICAgZHBseXI6Om11dGF0ZSgKICAgICAgdWNfY2F0ZWdvcnkgPSBzdHJpbmdpOjpzdHJpX2V4dHJhY3RfZmlyc3Rfd29yZHMoCiAgICAgIHVjX25hbWUKICAgICksCiAgICAjIGFicmV2aWEgbyBub21lIGRhcyBVQ3MKICAgIHVjX25hbWVfYWJ2ID0gZm9yY2F0czo6bHZsc19yZXZhbHVlKAogICAgICB1Y19uYW1lLAogICAgICBuZXdfbGV2ZWxzID0gYygKICAgICAgICAiRVRNIiwgIkVNIiwgIkVOIiwgIkVTR1QiLCAiRkoiLCAiUENWIiwgIlBBIiwgIlBTQm9jIiwgIlBTQm9kIiwgIlBTQyIsCiAgICAgICAgIlBTTSIsICJQU0MiLCAiUFNEIiwgIlBTUCIsICJQU08iLCAiUFBOIiwgIlBDTyIsICJQSSIsICJQSmHDuiIsICJQSnVyIiwKICAgICAgICAiUE1SIiwgIlBTIiwgIlBWIiwgIlBDQSIsICJQTVQiLCAiUkciLCAiUkoiLCAiUlRhcCIsICJSVSIsICJSRyIsCiAgICAgICAgIlJUcm9tIiwgIlJBVCIsICJSQkEiLCAiUkNJIiwgIlJDTSIsICJSUkMiLCAiUlJPUCIsICJSSUEiLCAiUlJBIiwgIlJUQSIKICAgICAgKQogICAgKSwKICAgICAgIyBhdHJpYnVpciBvIHRpcG8gZGF0YSDDoCBjb2x1bmEgc2FtcGxpbmdfZGF5CiAgICAgIHllYXIgPSBsdWJyaWRhdGU6OnllYXIoCiAgICAgICAgc2FtcGxpbmdfZGF5CiAgICAgICksCiAgICAgICMgYXRyaWJ1aXIgbyB0aXBvIGZhdG9yIMOgcyBjb2x1bmFzIGRvIHRpcG8gY2FyYWN0ZXIKICAgICAgYWNyb3NzKAogICAgICAgIHdoZXJlKAogICAgICAgICAgaXMuY2hhcmFjdGVyCiAgICAgICAgKSwKICAgICAgICBhcy5mYWN0b3IKICAgICAgKSwKICAgICAgIyBzdWJzdGl0dWlyIHNlcGFyYWRvcmVzIGRlIG5vbWUgcG9yICIsIgogICAgICBub3ZvID0gc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKAogICAgICAgIG9ic2VydmFkb3JlcywgCiAgICAgICAgIiBlICIsCiAgICAgICAgIiwgIgogICAgICApLAogICAgICAjIHN1YnN0aXR1aXIgc2VwYXJhZG9yZXMgZGUgbm9tZSBwb3IgIiwiCiAgICAgIG5vdm8gPSBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwoCiAgICAgICAgbm92bywgCiAgICAgICAgIiBFICIsCiAgICAgICAgIiwgIgogICAgICApLAogICAgICAjIHN1YnN0aXR1aXIgc2VwYXJhZG9yZXMgZGUgbm9tZSBwb3IgIiwiCiAgICAgIG5vdm8gPSBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwoCiAgICAgICAgbm92bywgCiAgICAgICAgIi8iLAogICAgICAgICIsICIKICAgICAgKSwKICAgICAgIyBzdWJzdGl0dWlyIHNlcGFyYWRvcmVzIGRlIG5vbWUgcG9yICIsIgogICAgICBub3ZvID0gc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKAogICAgICAgIG5vdm8sIAogICAgICAgICI7IiwKICAgICAgICAiLCAiCiAgICAgICksCiAgICAgICMgc3Vic3RpdHVpciBzZXBhcmFkb3JlcyBkZSBub21lIHBvciAiLCIKICAgICAgbm92byA9IHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCgKICAgICAgICBub3ZvLCAKICAgICAgICAiIGEgIiwKICAgICAgICAiLCAiCiAgICAgICkgCiAgICApIHw+CiAgIyB0cmFuc2Zvcm1hciBvcyBub21lcyBkb3Mgb2JzZXJ2YWRvcmVzIGRhIGNvbHVuYSBub3ZvIGVtIGNvbHVuYXMgaW5kaXZpZHVhaXMKdGlkeXI6OnNlcGFyYXRlX3dpZGVyX2RlbGltKAogIG5vdm8sIAogICIsIiwKICBuYW1lcyA9IGMoCiAgICAib2JzMSIsICJvYnMyIiwgIm9iczMiLCAib2JzNCIsICJvYnM1IiwgIm9iczYiCiAgKSwKICB0b29fZmV3ID0gImFsaWduX3N0YXJ0IgopIHw+IAogICMgZ2VyYXIgdW1hIG5vdmEgY29sdW5hIG51bWJlcl9vYnNlcnZlcnMgY29tIG8gbsO6bWVybyB0b3RhbCBkZSBvYnNlcnZhZG9yZXMgZW0gdW0gbWVzbW8gdHJhbnNlY3RvCiAgZHBseXI6Om11dGF0ZSgKICAgICMgc2UgbyB2YWxvciBkYSBvYnNlcnZhw6fDo28gw6kgZGlmZXJlbnRlIGRlIE5BLCBzdWJzdGl0dWlyIHBvciAxLCBzZSBmb3IgTkEsIHN1YnN0aXR1aXIgcG9yIDAKICAgIG9iczEgPSBpZmVsc2UoIWlzLm5hKG9iczEpLCAxLCAwKSwKICAgIG9iczIgPSBpZmVsc2UoIWlzLm5hKG9iczIpLCAxLCAwKSwKICAgIG9iczMgPSBpZmVsc2UoIWlzLm5hKG9iczMpLCAxLCAwKSwKICAgIG9iczQgPSBpZmVsc2UoIWlzLm5hKG9iczQpLCAxLCAwKSwKICAgIG9iczUgPSBpZmVsc2UoIWlzLm5hKG9iczUpLCAxLCAwKSwKICAgIG9iczYgPSBpZmVsc2UoIWlzLm5hKG9iczYpLCAxLCAwKSwKICAgICMgZ2VyYSBub3ZhIGNvbHVuYSBudW1iZXJfb2JzZXJ2ZXJzIGEgcGFydGlyIGRhIHNvbWEgZGFzIGNvbHVuYXMgZGUgb2JzZXJ2YWRvcmVzIGluZGl2aWR1YWlzCiAgICBudW1iZXJfb2JzZXJ2ZXJzID0gb2JzMSArIG9iczIgKyBvYnMzICsgb2JzNCArIG9iczUgKyBvYnM2CiAgKSB8PiAKICAjIGFncnVwYXIgb3MgZGFkb3MgcGVsYXMgY29sdW5hcyBlYV9uYW1lIGUgc2FtcGxpbmdfZGF5CiAgZ3JvdXBfYnkoCiAgICBlYV9uYW1lLCAKICAgIHNhbXBsaW5nX2RheQogICkgfD4gCiAgIyBhbmluaGFyIGFzIG9ic2VydmHDp8O1ZXMgYWdydXBhZGFzIHVlbSBsaXN0YXMKICBuZXN0KCkgfD4gCiAgIyBjb21wbGV0YXIgY29tIG8gdmFsb3IgY29ycmV0byBhcyBsaW5oYXMgdmF6aWFzIGRhcyBkYSB2YXJpw6F2ZWwgZGF5X2VmZm9ydAogIG11dGF0ZSgKICAgIGRheV9lZmZvcnQyID0gcHVycnI6Om1hcCgKICAgICAgZGF0YSwgXCgueCkgcmVwKAogICAgICAgIC54JGRheV9lZmZvcnRbCiAgICAgICAgICAhaXMubmEoCiAgICAgICAgICAgIC54JGRheV9lZmZvcnQKICAgICAgICAgICkKICAgICAgICBdWzFdCiAgICAgICkKICAgICkKICApIHw+IAogICMgZGVzYW5paGFyIG9zIGRhZG9zCiAgdW5uZXN0KAogICAgYygKICAgICAgZGF0YSwgCiAgICAgIGRheV9lZmZvcnQyCiAgICApCiAgKSB8PiAKICAjIGRlc2FncnVwYXIgb3MgZGFkb3MKICB1bmdyb3VwKCkgfD4gCiAgIyBzZWxlY2lvbmFyIGFzIGNvbHVuYXMgZGVzZWphZGFzIGUgZXhjbHVpciBhcyBpbmRlc2VqYWRhcwogIHNlbGVjdCgKICAgIHRpZHlzZWxlY3Q6OnN0YXJ0c193aXRoKGMoInVjIiwgImVhIikpLAogICAgc2Vhc29uLAogICAgeWVhciwKICAgIHNhbXBsaW5nX2RheSwKICAgIGRheV9lZmZvcnQgPSBkYXlfZWZmb3J0MiwKICAgIHNwOm51bWJlcl9vYnNlcnZlcnMsCiAgICAtZGF5X2VmZm9ydCwKICAgIC10aWR5c2VsZWN0OjpzdGFydHNfd2l0aCgib2JzIikKICApIHw+CiAgIyBmaWx0cmFyIG9zIGRhZG9zIHBlbGEgVUMgZSBlc3DDqWNpZSBkZXNlamFkYXMKICAgIGRwbHlyOjpmaWx0ZXIoCiAgICAgIHVjX25hbWUgPT0gIlJlc2V4IFRhcGFqb3MtQXJhcGl1bnMiLAogICAgICBzcCA9PSAiRGFzeXByb2N0YSBjcm9jb25vdGEiCiAgICApIHw+IAogIHJlbG9jYXRlKAogICAgdWNfY2F0ZWdvcnksCiAgICAuYmVmb3JlID0gdWNfbmFtZQogICkgfD4gCiAgcmVsb2NhdGUoCiAgICB1Y19uYW1lX2FidiwKICAgIC5hZnRlciA9IHVjX25hbWUKICApCgojIGdlcmFyIHRhYmVsYSBkaW7Dom1pY2EgZG9zIGRhZG9zIGNvbXBsZXRvcwpkYWRvc19maWx0cmFkb3MgfD4gCiAgc2xpY2UoCiAgICAxOjEwMDAKICApIHw+IAogIGRhdGF0YWJsZSgKICAgIGZpbHRlciA9IGxpc3QoCiAgICAgIHBvc2l0aW9uID0gInRvcCIKICAgICkKICApCmBgYAoKTyB0cmVjaG8gZG8gY8OzZGlnbyBxdWUgdmFpIGRhIGxpbmhhIDk2IGEgMTA2IHNlcnZlIHNlbGVjaW9uYXIgYXBlbmFzIGFzIGNvbHVuYXMgZGUgaW50ZXJlc3NlIHByZXNlbnRlIG5vcyBkYWRvcyBvcmlnaW5haXMuIE5vdGUgcXVlIG9zIG5vbWVzIGRhcyBwbGFuaWxoYXMgb3JpZ2luYWlzIGNvbnN0YW0gbmVzc2UgdHJlY2hvLiBDYXNvIG8gbm9tZSBkZSBxdWFscXVlIHVtYSBkZXNzYXMgY29sdW5hcyBzZWphIGFsdGVyYWRvIGEgZnVuw6fDo28gZGVpeGFyw6EgZGUgZnVuY2lvbmFyLgoKT3V0cm8gYXNwZWN0byBpbXBvcnRhbnRlIMOpIGEgcHJlc2Vuw6dhIGRlIG9ic2VydmHDp8O1ZXMgbsOjbyBwcmVlbmNoaWRhcwooZXguIGPDqWx1bGFzIHZhemlhcykgbm9zIGRhZG9zIG9yaWdpbmFpcy4gQSBmdW7Dp8OjbyBmb2kgZGVzZW5oYSBwYXJhCnJlc29sdmVyIGFsZ3VucyBwcm9ibGVtYXMgcHJlc2VudGVzIG5vcyBkYWRvcyBvcmlnaW5haXMuIFBvciBleGVtcGxvLApuYXMgbyB0cmVjaG8gZG8gY8OzZGlnbyBkYXMgbGluaGFzIDE5NCBhIDIxMCBhcyBvYnNlcnZhw6fDtWVzIHZhemlhcyAoYE5BYHMpIHPDo28gc3Vic3RpdHVpZGFzIHBlbG8gdmFsb3IgY29ycmV0byBuYSBjb2x1bmEgYGRheV9lZmZvcnRgLiBFc3NhIGNvcnJlw6fDo28gY29udGlubnVhcsOhIHNlbmRvIHJlYWxpemFkYSBlbSB2ZXJzw7VlcyBhdHVhbGl6YWRhcyBkb3MgZGFkb3MgZG8gTW9uaXRvcmEuIFBvcsOpbSwgc2Ugb3V0cmFzIGNvbHVuYXMgYWzDqW0gZGFzIHF1ZSBlc3TDo28gc2VuZG8gY29ycmlnaWRhcyBwb3NzdWlyZW0gb2JzZXJ2YcOnw7VlcyB2YXppYXMgb3MgZGFkb3Mgc2Vyw6NvIGNhcnJlZ2Fkb3MgZSB0cmFuc2Zvcm1hZG9zLCBwb3LDqW0gb3V0cmFzIGZ1bsOnw7VlcyBwb2RlbSB0ZXIgbyBzZXUgZnVuY2lvbmFtZW50byBjb21wcm9tZXRpZG8uIFBvciBleGVtcGxvLCBmdW7Dp8O1ZXMgZGUgdmlzdWFsaXphw6fDo28gZSBkbyBwYWNvdGUgYERpc3RhbmNlYCBxdWUgcG9kZW0gbsOjbyBmdW5jaW9uYXIgZGV2aWRvIGEgYXVzw6puY2lhIGRlIG9ic2VydmHDp8Ojby4KCkRlbnRyZSB0b2RhcyBhcyBmdW7Dp8O1ZXMgZGUgY2FycmVnYW1lbnRvIGRlIGRhZG9zLCBhcGVuYXMKYGNhcnJlZ2FyX2RhZG9zX2JydXRvc194bHN4KClgIGNhcnJlZ2EgYSBiYXNlIGRlIGRhZG9zIG9yaWdpbmFpcyBkbwpNb25pdG9yYSwgZGlyZXRhbWVudGUgZG8gZGlyZXTDs3JpbyBgZGF0YS1yYXcvbW9uaXRvcmFfbWFzdG9fYXZlc18yMDIzXzA0XzA0Lnhsc3hgLiBBbyBtZXNtbyB0ZW1wbyBxdWUKY2FycmVnYSBlIHRyYW5zZm9ybWEgb3MgZGFkb3MsIGVzc2EgZnVuw6fDo28gZ2VyYSB1bWEgdmVyc8OjbyBlbSB1bSBmb3JtYXRvIG1haXMgbGV2ZSwgYC5yZHNgLCBubyBkaXJldMOzcmlvIGBkYXRhLXJhd2AgKGBkYXRhLXJhdy9tb25pdG9yYV9tYXN0b19hdmVzXzIwMjNfMDRfMDQucmRzYCkuIEEgZnVuw6fDo28gc2VndWludGUgbm8KZmx1eG8gZGUgdHJhYmFsaG8gY2FycmVnYSBhIGJhc2UgYSBwYXJ0aXIgZGVzc2EgdmVyc8OjbyBtYWlzIGxldmUuIExvZ28sIHNlbXByZSBxdWUgaG91dmVyIGF0dWFsaXphw6fDtWVzIG5vIGFycXVpdm8gb3JpZ2luYWwgZGUgZGFkb3MgYnJ1dG9zIMOpIG5lY2Vzc8OhcmlvIGluaWNpYXIgYSByb3RpbmEgZGUgY2FycmVnYW1lbnRvIGRlIGRhZG9zIG5lY2Vzc2FyaWFtZW50ZSBjb20gYSBmdW7Dp8OjbyBgY2FycmVnYXJfZGFkb3NfYnJ1dG9zX3hsc3goKWAuCgojICoqUEFSVEUgSUkgLS0gQ2FycmVnYW5kbyBvcyBkYWRvcyBwYXJhIG8gUioqCgojIyAqKkRhZG9zIGJydXRvcyoqCgpOw6NvIHByZWNpc2Egc2UgYXNzdXN0YXIgY29tIGEgaW5maW5pZGFkZSBkZSBjw7NkaWdvcyBubyBleGVtcGxvIGFjaW1hLgpFbGVzIGZvcmFtIHV0aWxpemFkb3MgYXBlbmFzIHBhcmEgaWx1c3RyYXIgcXVlIGNvbnN0cnVpciBlc3NhcyBmdW7Dp8O1ZXMgZmFjaWxpdGEgYSBleGVjdcOnw6NvIGUgYSByZXByb2R1dGliaWxpZGFkZSBkYXMgYW7DoWxpc2UgZG9zIGRhZG9zIGRvIE1vbml0b3JhLiBQYXJhIGNhZGEgdGFyZWZhIGV4aXN0ZSB1bWEgZnVuw6fDo28gY3VqbyBmdW5jaW9uYW1lbnRvIG5lY2Vzc2l0YSBvIHByZWVuY2hpbWVudG8gZGUgYWxndW5zIGFyZ3VtZW50b3MsIG91IG1lc21vIGRlIG5lbmh1bSAoZW1ib3JhIHNlamEgc2VtcHJlIHBvc3PDrXZlbCBmb3JuZWPDqi1sb3MpLiBQb3IKdHJheiBkYXMgY29ydGluYXMsIGFzIGZ1bsOnw7VlcyBleGVjdXRhbSBhcyB0YXJhZmFzIG5lY2Vzc8OhcmlhcyBwYXJhIHNlCm9idGVyIG8gcmVzdWx0YWRvIGRlc2VqYWRvLiBQb3IgZXhlbXBsbywgbyBtZXNtbyByZXN1bHRhZG8gcG9kZSBzZXIKb2J0aWRvIHV0aWxpemFuZG8gYXBlbmFzIGR1YXMgZnVuw6fDtWVzOiBgY2FycmVnYXJfZGFkb3NfYnJ1dG9zX3hsc3goKWBlCmBnZXJhcl90YWJkaW5fZGFkb3NfYnJ1dG9zKClgLgoKYGBge3J9CiMgY2FycmVnYXIgZGFkb3MgYnJ1dG9zCmRhZG9zX2JydXRvcyA8LSBjYXJyZWdhcl9kYWRvc19icnV0b3NfeGxzeCgpCgojIGdlcmFyIHRhYmVsYSBkaW5hbWljYSBkb3MgZGFkb3MgYnJ1dG9zCmdlcmFyX3RhYmRpbl9kYWRvc19icnV0b3MoKQpgYGAKCkEgZnVuw6fDo28gYGdlcmFyX3RhYmRpbl9kYWRvc19icnV0b3MoKWAsIHBvciBjb25maWd1cmHDp8OjbywgZ2VyYSB1bWEKdGFiZWxhIGRpbsOibWljYSBjb20gMTAwMCBsaW5oYXMuIFZvY8OqIHBvZGUgY29udHJvbGFyIG8gbsO6bWVybyBkZSBsaW5oYXMgcGVsbyBhcmd1bWVudG8gYG5fbGluaGFzID1gLiBNYXMgYXRlbsOnw6NvISBFbGEgbsOjbyBmdW5jaW9uYXLDoSBjb20gdW0gbsO6bWVybyBzdXBlcmlvciBhICoqNC41MDAgbGluaGFzKiouIEFvIG11ZGFyIGEgZW50cmFkYSBkZSBkYWRvcyB1c2FuZG8gbyBhcmd1bWVudG8gYGRhZG9zID1gLCBjZXJ0aWZpcXVlLXNlIGRlIHF1ZSBzZXUgbsO6bWVybyBkZSBsaW5oYXMgbsOjbyBleGNlZGEgZXNzZSBsaW1pdGUgKGV4LiAqKjQuNTAwKiopLiAKCmBgYHtyfQpnZXJhcl90YWJkaW5fZGFkb3NfYnJ1dG9zKAogIG5fbGluaGFzID0gMTo0NTAwCikKYGBgCgojIyAqKkRhZG9zIGNvbXBsZXRvcyoqCgpgYGB7cn0KIyBjYXJyZWdhciBkYWRvcyBwYXJhIG8gUgpkYWRvc19jb21wbGV0b3MgPC0gY2FycmVnYXJfZGFkb3NfY29tcGxldG9zKCkgCgojIGdlcmFyIHRhYmVsYSBkaW5hbWljYSBkb3MgZGFkb3MgY29tcGxldG9zCmdlcmFyX3RhYmRpbl9kYWRvc19jb21wbGV0b3MoKQpgYGAKCiMjICoqRGFkb3MgZmlsdHJhZG9zKioKCmBgYHtyfQojIGNhcnJlZ2FyIGRhZG9zIHBhcmEgbyBSCmRhZG9zX2ZpbHRyYWRvcyA8LSBjYXJyZWdhcl9kYWRvc19maWx0cmFkb3MoKQoKIyBnZXJhciB0YWJlbGEgZGluw6JtaWNhIGRvcyBkYWRvcyBmaXRyYWRvcwpnZXJhcl90YWJkaW5fZGFkb3NfZmlsdHJhZG9zKCkKYGBgCgojICoqUGFydGUgSUlJIC0tIFRyYW5zZm9ybWFuZG8gZGFkb3MgcGFyYSBEaXN0YW5jZSoqCgojIyAqKkRhZG9zIGNvbXBsZXRvcyBubyBmb3JtYXRvIERpc3RhbmNlKioKCmBgYHtyfQojIHRyYW5zZm9ybWFyIG9zIGRhZG9zIHBhcmEgbyBmb3JtYXRvIGRvIERpc3RhbmNlCmRhZG9zX2Rpc3RhbmNlUl9jb21wbGV0byA8LSB0cmFuc2Zvcm1hcl9wYXJhX2Rpc3RhbmNlUl9jb3ZhcmlhdmVpcygpCgojIGdlcmFyIHRhYmVsYSBkaW5hbWljYSBkb3MgZGFkb3Mgbm8gZm9ybWF0byBkbyBkaXN0YW5jZSBkbyBSCmdlcmFyX3RhYmRpbl9kYWRvc19zZWxlY2lvbmFkb3NfZGlzdGFuY2VSX2NvdigpCmBgYAoKIyAqKlBBUlRFIElWIC0tIEV4cGxvcmFuZG8gZSBzZWxlY2lvbmFuZG8gb3MgZGFkb3MgcGFyYSBhcyBhbsOhbGlzZXMqKgoKQXByZXNlbnRhbW9zIGFiYWl4byB1bSBjb25qdW50byBkZSBmZXJyYW1lbnRhcyBxdWUgcGVybWl0ZSBkaXZlcnNhcyBmb3JtYXMgZGUgZXhwbG9yYXIgdG9kbyBvIGNvbmp1bnRvIGRlIGRhZG9zLgoKIyMgKipTZWxlY2lvbmFuZG8gb3MgbWVsaG9yZXMgZXNww6ljaWVzIG1vZGVsbyBkZSBlc3R1ZG8gZGUgYWNvcmRvIGNvbSBvcyBkYWRvcyoqCgpBbGd1bnMgY3VpZGFkb3MgZGV2ZW0gc2VyIHRvbWFkb3MgbmEgcHJlcGFyYcOnw6NvIGRvcyBkYWRvcyBhbnRlcyBkZSBzZXJlbSBhbmFsaXNhZG9zLiBPIHByaW1laXJvIGRlbGVzIMOpIG8gY3VpZGFkbyB0YXhvbsO0bWljby4gUGFyYSBvcyBkYWRvcyBkbyBNb25pdG9yYSByZWNvbWVuZGEtc2UgbyB1c28gZG9zIGRhZG9zIGRhcyBlc3DDqWNpZXMgdmFsaWRhZGFzIHBhcmEgYW7DoWxpc2UgcGVsbyBJQ01CaW8sIGNvbmZvcm1lIG8gbW9kZWxvIHV0aWxpemFkbyBwYXJhIGVzdGUgZmx1eG8gZGUgdHJhYmFsaG8uCgpBbGd1bnMgcHJvYmxlbWFzIGNvbSBvcyBkYWRvcywgcXVlIHBvZGVtIHRyYXplciBlZmVpdG9zIGluZGVzZWphZG9zCnNvYnJlIGFzIGFuw6FsaXNlcywgcG9kZW0gc2VyIGRldGVjdGFkb3MgZHVyYW50ZSBhIGZhc2UgZGUgZXhwbG9yYcOnw6NvLiBBbyBzZWxlY2lvbmFyIG9zIGRhZG9zIHF1ZSBzZXLDo28gYW5hbGlzYWRvcywgw6kgaW1wb3J0YW50ZSBvYnNlcnZhciBvcwpzZWd1aW50ZXMgYXNwZWN0b3M6CgoqKlN1Zmljw6puY2lhIEFtb3N0cmFsIC0gbsO6bWVybyBkZSBvY29ycsOqbmNpYXMgcG9yIGVzcMOpY2llKioKClBhcmEgcXVlIG8gbcOpdG9kbyBkZSBhbsOhbGlzZSBwb3IgZGlzdMOibmNpYSBwb3NzYSBzZXIgdXRpbGl6YWRvIHBhcmEKZXN0aW1hdGl2YXMgYmFzZWFkYXMgZW0gbW9kZWxvcywgc8OjbyByZWNvbWVuZGFkYXMgcXVhbnRpZGFkZXMgbcOtbmltYXMgZGUgcmVnaXN0cm9zIGRlIG9jb3Jyw6puY2lhIGUgZGUgdHJhbnNlY3RvcyAoVW5pZGFkZXMgQW1vc3RyYWlzKS4gU2VndW5kbyBCVUNLTEFORCBldC4gYWwuICgyMDE1KSwgbyBuw7ptZXJvIG3DrW5pbW8gc3VnZXJpZG8gZGUgYW5pbWFpcyBvdSBncnVwb3MgKG9jb3Jyw6puY2lhcykgw6kgZGUgNjAgLS0gODAgYW5pbWFpcyAob3UgZ3J1cG9zKSBxdWFuZG8gYSBhbW9zdHJhZ2VtIMOpIGZlaXRhIHBlbG8gbcOpdG9kbyBkb3MgdHJhbnNlY3RvcyBsaW5lYXJlcy4gw4kgcG9zc8OtdmVsIHV0aWxpemFyIG7Dum1lcm9zIG1lbm9yZXMgcXVlIGVzdGVzIHBhcmEgcmVhbGl6YXIgYXMgYW7DoWxpc2VzLCBwb3LDqW0gZGV2ZS1zZSB0ZXIgbyBjdWlkYWRvIGRlIHZlcmlmaWNhciBzZSBhcyBmdW7Dp8O1ZXMgZGUgZGV0ZWPDp8OjbyBlc3TDo28gYmVtIG1vZGVsYWRhcy4KClBhcmEgZGFkb3MgcXVlIHNlcsOjbyBlc3RyYXRpZmljYWRvcyAoZGl2aWRpZG9zIGVtIHN1YmNvbmp1bnRvcyksIGVzdGVzIG7Dum1lcm9zIHJlY29tZW5kYWRvcyBzZSBhcGxpY2FtIGEgY2FkYSBzdWJjb25qdW50by4gSXNzbyBvY29ycmUgcG9ycXVlIGFzIGZ1bsOnw7VlcyBkZSBkZXRlY8Onw6NvIHNlcsOjbyBtb2RlbGFkYXMgcGFyYSBjYWRhIGVzdHJhdG8KKHAuZXguYFJlZ2lvbi5MYWJlbGApLCBhbMOpbSBkYSBmdW7Dp8OjbyBkZSBkZXRlY8Onw6NvIHBhcmEgb3MgZGFkb3MgZ2xvYmFpcy4gVW0gZXhlbXBsbyBzZXJpYSBhIGFuw6FsaXNlIGRvcyBkYWRvcywgcGFyYSB1bWEgbWVzbWEgZXNww6ljaWUsIGVtIGRpZmVyZW50ZXMgVUNzLiBOZXN0ZSBjYXNvLCBvIGlkZWFsIHNlcmlhIHRlciBhIHN1ZmljacOqbmNpYSBhbW9zdHJhbCBtw61uaW1hIGVtIGNhZGEgVUMgcGFyYSB1c2FyIGVzdHJhdGlmaWNhw6fDo28gZSBlc3RpbWFyIGFidW5kw6JuY2lhcyBlIGRlbnNpZGFkZXMgZW0gY2FkYSB1bWEgZGFzIFVDcy4KCioqU3VmaWNpw6puY2lhIGFtb3N0cmFsIC0gcsOpcGxpY2FzIGUgcmVwZXRpw6fDtWVzKioKClBhcmEgcXVlIGhhamEgdW1hIGJvYSBjb2JlcnR1cmEgZGEgw6FyZWEgZGUgZXN0dWRvIGUgdGFtYsOpbSB1bWEgYm9hCnF1YW50aWRhZGUgZGUgYW1vc3RyYXMgaW5kZXBlbmRlbnRlcyBwYXJhIGVzdGltYXIgYXMgYWJ1bmTDom5jaWFzIGUKZGVuc2lkYWRlcyBkYXMgZXNww6ljaWVzLCDDqSBkZXNlasOhdmVsIHVtIG7Dum1lcm8gc2F0aXNmYXTDs3JpbyBkZSByw6lwbGljYXMgaW5kZXBlbmRlbnRlcy4gU2VndW5kbyBCVUNLTEFORCBldCBhbC4gKDIwMTUpLCBvIG7Dum1lcm8gbcOtbmltbyBkZSByw6lwbGljYXMgaW5kZXBlbmRlbnRlcyBwYXJhIG9zIHRyYW5zZWN0b3MgZGV2ZSBzZXIgZGUgMTAtMjAsIG8gcXVlIGRldmUgYXVtZW50YXIgcGFyYSBlc3DDqWNpZXMgY3VqYXMgcG9wdWxhw6fDtWVzIHPDo28gZGlzdHJpYnXDrWRhcyBlbSBtYW5jaGFzLgoKRGUgZm9ybWEgZ2VyYWwsIHBhcmEgY2FkYSBVQywgbyBuw7ptZXJvIGRlIHLDqXBsaWNhcyBkbyBQcm9ncmFtYSBNb25pdG9yYSBlc3TDoSBhYmFpeG8gZG8gcmVjb21lbmRhZG8uIE8gZGVsaW5hbWVudG8gYW1vc3RyYWwgYXR1YWwgcGFyYSBhIGNvbXBvbnRlbnRlIEZsb3Jlc3RhbCBkbyBzdWJwcm9ncmFtYSBUZXJyZXN0cmUgZXN0YWJlbGVjZSB1bSBuw7ptZXJvIG3DrW5pbW8gZGUgdHLDqnMgRXN0YcOnw7VlcyBBbW9zdHJhaXMgcG9yIFVuaWRhZGUgZGUgQ29uc2VydmHDp8OjbywgbyBxdWUgw6kgbyBjYXNvIGRlIG11aXRhcyBVQ3MsIGNoZWdhbmRvIGFvIG3DoXhpbW8gZGUgOSBlc3Rhw6fDtWVzIGFtb3N0cmFpcyBwb3IgVUMuIE8gYmFpeG8gbsO6bWVybyBkZSByw6lwbGljYXMgZXNwYWNpYWlzIGlkZXBlbmRlbnRlcyBuw6NvIGNoZWdhIGEgc2VyIHVtIHByb2JsZW1hIG5hIGVzdGltYXRpdmEgZGUgZGVuc2lkYWRlIGRhIMOBcmVhIENvYmVydGEgcGVsYSBhbW9zdHJhZ2VtLCBtYXMgbGltaXRhIHVtYSBib2EgZXN0aW1hdGl2YSBkZSBkZW5zaWRhZGUgdG90YWwgcGFyYSBhIFVuaWRhZGUgZGUgQ29uc2VydmHDp8Ojby4KClVtIG91dHJvIGFzcGVjdG8gcmVsYWNpb25hZG8gYSBhbW9zdHJhZ2VtIMOpIG8gbsO6bWVybyBkZSByZXBldGnDp8O1ZXMgcG9yIHRyYW5zZWN0by4gU2VndW5kbyBCVUtMQU5EIGV0IGFsICgyMDAxLCBwZyA3OSksIGFzIHJlcGV0acOnw7VlcyBkZXZlbSBzZXIgaW5jb3Jwb3JhZGFzIG5vIGVzZm9yw6dvIGFtb3N0cmFsIG11bHRpcGxpY2FuZG8tc2UgbyBuw7ptZXJvIGRlIHZlemVzIHF1ZSBvIHRyYW5zZWN0byBmb2kgcGVyY29ycmlkbyBwZWxvIGNvbXByaW1lbnRvIGRvIHRyYW5zZWN0by4gQSBtZXNtYSByZWNvbWVuZGHDp8OjbyDDqSBkYWRhIHBlbG8gQ3Vyc28gT25saW5lIGVtIERpc3RhbmNlIFNhbXBsaW5nIFtsaW5rXShodHRwczovL3dvcmtzaG9wcy5kaXN0YW5jZXNhbXBsaW5nLm9yZy9vbmxpbmUtY291cnNlL2xlY3R1cmVwZGZzL0NoNC9MNC0zJTIwU2FtcGxlJTIwU2l6ZS5wZGYpLiBFc3NlIGFqdXN0ZSBubyBlc2ZvcsOnbyBhbW9zdHJhbCBuw6NvIGRldmUgdGVyIGdyYW5kZXMgY29uc2VxdcOqbmNpYXMgcGFyYQp1bSBiYWl4byBuw7ptZXJvIGRlIHJlcGV0acOnw7Vlcy4gUG9yw6ltLCBuw7ptZXJvcyBhbHRvcyBkZSBhbW9zdHJhZ2VucyByZXBldGlkYXMgZSBuw6MgaW5kZXBlbmRlbnRlcyBsZXZhbSBhIHVtYSBpbmZsYWdlbSBubyB0YW1hbmhvIGRhIMOhcmVhIGNvYmVydGEuIEFwZW5hcyBwYXJhIGlsdXN0YXIgY29tIHVtIGV4ZW1wbG8sIHBhcmEgb3MgZGFkb3MgZGEgY3V0aWEgKkRhc3lwcm9jdGEgY3JvY29ub3RhKiBkYSBSZXNleCBUYXBhasOzcy1BcmFwaW51bnMsIGEgRXN0YcOnw6NvIEFtb3N0cmFsIEJvaW0gZm9pIHBlcmNvcnJpZGEgZHVyYW50ZSA3MCBkaWFzIGRlIGFtb3N0cmFnZW0uIElzc28gc2lnbmlmaWNhIHF1ZSBhanVzdGFuZG8gbyBjb21wcmltZW50byBkbyB0cmFuc2VjdG8gZGUgNSBrbSBwZWxvIG7Dum1lcm8gZGUgcmVwZXRpw6fDtWVzLCBvIGVzZm9yw6dvIGFtb3N0cmFsIHBhc3NvdSBwYXJhIDM1MCBrbS4gQSDDoXJlYSBjb2JlcnRhIGF1bWVudG91IGVtIDcweCwgbyBxdWUgdGVyw6EgY29uc2VxdcOqbmNpYXMgc29icmUgYSBlc3RpbWF0aXZhIGRlbnNpZGFkZSwgcXVlIHRlbmRlcsOhIGEgc2VyIHN1YmVzdGltYWRhLiBBbMOpbSBkaXNzbywgbyBjb2VmaWNpZW50ZSBkZSB2YXJpYcOnw6NvIGRhcyBlc3RpbWF0aXZhcyBkZSB0YXhhIGRlIGVuY29udHJvLCBhYnVuZMOibmNpYSBlIGRlbnNpZGFkZSB0YW1iw6ltIHRlbmRlcsOjbyBhIGF1bWVudGFyIHBlbG8gZWZlaXRvIGRhIHZhcmlhw6fDtWVzIHRlbXBvcmFpcyBlbnRyZSBhcyBhbW9zdHJhZ2Vucy4KClVtYSBmb3JtYSBkZSBsaWRhciBjb20gbyBleGNlc3NvIGRlIGFtb3N0cmFnZW5zIHJlcGV0aWRhcyDDqSB0cmF0YXIgYXMKcmVwZXRpw6fDtWVzIGNvbW8gZWZlaXRvcyBhbGVhdMOzcmlvcyBkb3MgbW9kZWxvcy4gSXNzbyByZXF1ZXIgbyB1c28gZGUKYWJvcmRhZ2VucyBxdWUgdsOjbyBhbMOpbSBkYSBhbW9zdHJhZ2VtIHBvciBkaXN0w6JuY2lhIGNvbnZlY2lvbmFsLCBjb21vIG8gdXNvIGRlIE1peGVkIEVmZmVjdCBNb2RlbHMgZSBNb2RlbG9zIEhpZXLDoXJxdWljb3MgKHAuIGV4LiBPRURFS09WRU4gZXQgYWwuIDIwMTMsIDIwMTQpLiBFc3NhcyBhYm9yZGFnZW5zIGFpbmRhIG7Do28gZm9yYW0gaW1wbGVtZW50YWRhcyBlbSBub3NzbyBmbHV4byBkZSB0cmFiYWxobyBhdMOpIGEgcHJlc2VudGUgdmVyc8OjbyBlIHByZXRlbmRlbW9zIHRlc3RhciBvcyBjw7NkaWdvcyBwYXJhIGVzdGEgYWJvcmRhZ2VtIHV0aWxpemFuZG8gbyBwYWNvdGUgdW5tYXJrZWQgYXTDqSBvIGZpbmFsIGRhIHZpZ8OqbmNpYSBkbyBwcmVzZW50ZSBwcm9qZXRvLgoKKipEaXN0cmlidWnDp8OjbyBkZSBmcmVxdcOqbmNpYSBkYXMgb2NvcnLDqm5jaWFzIGVtIHJlbGHDp8OjbyDDoCBkaXN0w6JuY2lhIC0KZWZlaXRvcyBpbmRlc2VqYWRvcyoqCgpBIGRpc3RyaWJ1acOnw6NvIGlkZWFsIGRhcyBmcmVxdcOqbmNpYXMgZGUgb2NvcnLDqm5jaWEgZW0gcmVsYcOnw6NvIMOgCmRpc3TDom5jaWEgZGV2ZSBhcHJlc2VudGFyIGFzIHNlZ3VpbnRlcyBjYXJhY3RlcsOtc3RpY2FzOiBhIGZyZXF1w6puY2lhIGRlIG9jb3Jyw6puY2lhIGRldmUgc2VyIG1haW9yIHByw7N4aW1vIGEgemVybywgYXByZXNlbnRhciB1bSBsb25nbyBwbGF0w7QgKG9tYnJvKSwgZSBkZWNhaXIgZ3JhZGF0aXZhbWVudGUgY29tIG8gYXVtZW50byBkYSBkaXN0w6JuY2lhLiBJc3NvIHNpZ25pZmljYSBxdWUgb3MgYW5pbWFpcyBzw6NvIHRvdGFsbWVudGUgZGV0ZWN0w6F2ZWlzIG5hIGRpc3TDom5jaWEgemVybywgc2VndWVtIHNlbmRvIGJlbSBkZXRlY3TDoXZlaXMgYSBkaXN0w6JuY2lhcyBjdXJ0YXMgZSB2w6NvIHBlcmRlbmRvCmRldGVjdGFiaWxpZGFkZSBncmFkYXRpdmFtZW50ZSBjb20gbyBhdW1lbnRvIGRhIGRpc3TDom5jaWEuCgpQb3IgaXNzbywgdW1hIGRhcyBldGFwYXMgZXhwbG9yYXTDs3JpYXMgw6kgYXZhbGlhciBvIGhpc3RvZ3JhbWEgZGUKZnJlcXXDqm5jaWFzIGRlIG9jb3Jyw6puY2lhIGFvIGxvbmdvIGRhIGRpc3TDom5jaWEgZW0gcmVsYcOnw6NvIGFvIHRyYW5zZWN0byAob3DDp8OjbyBhYmFpeG8pLiBBbGd1bWFzIGRpc3RyaWJ1acOnw7VlcyBpbmRpY2FtIHByb2JsZW1hcyBub3MgZGFkb3MgcXVlIHBvZGVtIGRpZmljdWx0YXIgbyBhanVzdGUgZGFzIGZ1bsOnw7VlcyBkZSBkZXRlY8Onw6NvLiBUYWlzIGNvbW86CgoqUGljbyBkZSBvY29ycsOqbmNpYXMgcHLDs3hpbW9zIMOgIGRpc3TDom5jaWEgemVybyAtIHNwaWtlIG5lYXIgemVybwpkaXN0YW5jZSoKCklzc28gb2NvcnJlIHF1YW5kbyBvIG7Dum1lcm8gZGUgb2JzZXJ2YcOnw7VlcyBwcsOzeGltb3Mgw6AgZGlzdMOibmNpYSB6ZXJvIMOpICBpbmZsYWRvIGVtIHJlbGHDp8OjbyDDoHMgZGVtYWlzIGRpc3TDom5jaWFzLiBPIGVmZWl0byBncsOhZmljbyBzZXLDoSB1bSBwaWNvIG5vIGhpc3RvZ3JhbWEgZW0gemVybyBvdSBwcsOzeGltbyBhIHplcm8sIGNvbmZvcm1lIG8gZXhlbXBsbyBhYmFpeG8gcGFyYSBvcyBkYWRvcyBleHRyYcOtZG9zIGRhcyBjdXRpYXMgKCpEYXN5cHJvY3RhIGNyb2Nvbm90YSopIG5hIFJlc2V4IFRhcGFqw7NzLUFyYXBpdW5zLgoKIVtEaXN0cmlidWljYW8gZGUgRnJlcXVlbmNpYSBwYXJhICpEYXN5cHJvY3RhIGNyb2Nvbm90YSogbmEgUmVzZXgKVGFwYWpvcy1BcmFwaXVuc10oYHIgaGVyZTo6aGVyZSgib3V0cHV0L0Rpc3RyaWJ1aWNhb19mcmVxX0Rhc3lwcm9jdGFfUmVzZXhUYXBham9zLnBuZyIpYCl7d2lkdGg9Ijc1JSJ9CgpFc3RlIHRpcG8gZGUgZGlzdHJpYnVpw6fDo28gZm9pIHByZWRvbWluYW50ZSBwYXJhIGFzIGVzcMOpY2llcyBjb20gbyBtYWlvciBuw7ptZXJvIGRlIG9jb3Jyw6puY2lhIG5vcyBkYWRvcyBkZSBhdmVzIGUgbWFtw61mZXJvcyBkbyBQcm9ncmFtYSBNb25pdG9yYSBGbG9yZXN0YWwuIEFjcmVkaXRhbW9zIHF1ZSBleGlzdGVtIGRvaXMgZmF0b3JlcyBxdWUgcG9kZW0gZXN0YXIgY2F1c2FuZG8gZXNzZSBhY8O6bXVsbyBkZSBkYWRvcyBlbSB6ZXJvIG91IHByw7N4aW1vIGEgZWxlLiBVbSBkZWxlcyBzZXJpYSB1bSB2acOpcyBwYXJhIGF2aXN0YW1lbnRvIGRlIGFuaW1haXMgbmEgdHJpbGhhIGVtIGFtYmllbnRlcyBkZSBmbG9yZXN0YS4gQXMgdHJpbGhhcyBwb2RlbSBhdHJhaXIgYW5pbWFpcywgZSB0YW1iw6ltIG9mZXJlY2VtIG1lbGhvciB2aXNpYmlsaWRhZGUgZW0gcmVsYcOnw6NvIMOgIGZsb3Jlc3RhLCBlc3BlY2lhbG1lbnRlIHNlIG8gc3ViLWJvc3F1ZSBmb3IgZGVuc28uIE8gb3V0cm8gZmF0b3Igc2VyaWEgdW0gcG9zc8OtdmVsIGFycmVkb25kYW1lbnRvIG5hcyBkaXN0w6JuY2lhcyBwcsOzeGltYXMgYSB6ZXJvLCBvIHF1ZSBwb2RlIGdlcmFyIHVtICJhbW9udG9hbWVudG8iIG5vcyBkYWRvcyAoKmhlYXBpbmcqKS4gUmVjb21lbmRhLXNlIHF1ZSB2YWxvcmVzIGRlIGRpc3TDom5jaWEgcGVycGVuZGljdWxhciBudW5jYSBzZWphbSBhcnJlZG9uZGFkb3MuCgoqUmVzcG9zdGEgZXZhc2l2YSBkYXMgZXNww6ljaWVzIGVtIHJlbGHDp8OjbyBhbyBvYnNlcnZhZG9yKgoKUGFyYSBlc3DDqWNpZXMgcXVlIHBvZGVtIGFwcmVzZW50YXIgcmVzcG9zdGEgZGUgZGVzbG9jYW1lbnRvIGVtIHJlbGHDp8OjbyBhbyBvYnNlcnZhZG9yLCB1bSBkb3MgZWZlaXRvcyBpbmRlc2VqYWRvcyBub3MgZGFkb3Mgw6kgbyBkZXNsb2NhbWVudG8gZGFzIG1haW9yZXMgZnJlcXXDqm5jaWFzIGRlIG9ic2VydmHDp8O1ZXMgcGFyYSBhcyBkaXN0w6JuY2lhcyBwZXJwZW5kaWN1bGFyZXMgaW50ZXJtZWRpw6FyaWFzIGFvIG1lc21vIHRlbXBvIHF1ZSBhcyBmcmVxdcOqbmNpYXMgcHLDs3hpbWFzIGFvIG9ic2VydmFkb3Igc8OjbyBiYWl4YXMuIFVtYSBhbHRlcm5hdGl2YSwgbmVzc2UgY2Fzbywgw6kgY29uc3RyYW5nZXIgYSBmdW7Dp8OjbyBkZSBkZXRlw6fDo28gcGFyYSBtb25vdG9uaWNpZGFkZSwgZXZpdGFuZG8gcXVlIGVsYSBzdWJhIHBhcmEgc2UgYWp1c3RhciBhbyBwaWNvIGRlIGZyZXF1w6puY2lhIG5hcyBkaXN0w6JuY2lhcyBpbnRlcm1lZGnDoXJpYXMuCgoqVmnDqXMgZGUgdGFtYW5obyBkZSBncnVwbyoKClVtIGRvcyBlZmVpdG9zIHF1ZSBwb2RlIG9jb3JyZXIgcGFyYSBlc3DDqWNpZXMgcXVlIGZvcm1hbSBncnVwb3MsIMOpIHF1ZSBncnVwb3MgbWVub3JlcyBwZXJkZW0gYSBkZXRlY3RhYmlsaWRhZGUgbWFpcyBmw6FjaWwgZG8gcXVlIGdydXBvcyBtYWlvcmVzIGNvbSBvIGF1bWVudG8gZGEgZGlzdMOibmNpYS4gRXNzZSB2acOpcyBwb2RlIHNlciB0ZXN0YWRvIG5hIGV4cGxvcmHDp8OjbyBkb3MgZGFkb3MgZGFzIGNvdmFyacOhdmllcywgcGxvdGFuZG8tc2UgdW0gZ3LDoWZpY28gZGUgdGFtYW5obyBkZSBncnVwbyBwZWxhIGRpc3TDom5jaWEuIENhc28gbyB2acOpcyBvY29ycmEsIHNlcsOhIHVtYSBvYnNlcnZhZGEgdW1hIHRlbmTDqm5jaWEgZGUgcmVnaXN0cm9zIHNvbWVudGUgZGUgZ3J1cG9zIG1haW9yZXMgbmFzIGRpc3TDom5jaWFzIG1haW9yZXMuIE7Ds3MgYWRvdGFtb3MgYSBlc3RyYXTDqWdpYSBkZSB0cmF0YXIgdGFtYW5obyBkZSBncnVwbyBjb21vIGNvdmFyacOhdmVsIHBhcmEgZXNww6ljaWVzIHF1ZSBmb3JtYW0gZ3J1cG9zLiBOZXN0ZSBjYXNvLCBhbyBtZXNtbyB0ZW1wbyBxdWUgbGlkYW1vcyBjb20gbyBlZmVpdG8gZG8gdGFtYW5obyBkbyBncnVwbyBuYSBkZXRlY3RhYmlsaWRhZGUsIGluY29ycG9yYW1vcyB0YW1iw6ltIG8gdGFtYW5obyBkbyBncnVwbyBuYXMgZXN0aW1hdGl2YXMgZGUgZGVuc2lkYWRlIGUgYWJ1bmTDom5jaWEuCgojIyMgKipFeHBsb3Jhw6fDo28gZSBzZWxlw6fDo28gZGUgZGFkb3MqKgoKIyMjIyAqKkFzcGVjdG9zIHJlbGFjaW9uYWRvcyBhbyBuw7ptZXJvIHRvdGFsIGRlIG9ic2VydmHDp8O1ZXMqKgoKIyMjIyAqKlF1YW50YXMgb2JzZXJ2YcOnw7VlcyBmb3JhbSB2YWxpZGFkYXMgcGFyYSBxdWFpcyBuw612ZWlzIHRheG9uw7RtaWNvcz8qKgoKRXNzYXMgb3BlcmHDp8O1ZXMgc8OjbyByZWFsaXphZGFzIHNvYnJlIGEgdGFiZWxhIGRlIGRhZG9zIGBkYWRvc19jb21wbGV0b3NgIHBvaXMgb3MgZGFkb3MgcXVlIGZvcmFtIHRyYW5zZm9ybWFkb3MgcGFyYSBvIGZvcm1hdG8gZG8gZGlzdGFjZSBubyBSIG7Do28gcG9zc3VlbSBhIGNvbHVuYSBgdmFsaWRhdGlvbmAsIG5lY2Vzc8OhcmlhIHBhcmEgZXNzYXMgb3BlcmVhw6fDtWVzLiBNYWlzIGEgZnJlbnRlIG8gcHJvY2VkaW1lbnRvIGRlIGNvbW8gb2J0ZXIgb3MgZGFkb3Mgc2VsZWNpb25hZG9zIGUgdHJhbnNmb3JtYXRvcyBwYXJhIG8gZm9ybWF0byBkYXMgYW7DoWxpc2VzIHNlcsOhIGRlbW9uc3RyYWRvLgoKYGBge3J9CiMgY29udGFyIG9ic2VydmHDp8O1ZXMgdmFsaWRhZGFzIGFvIG7DrXZlbCBkZSBlc3DDqWNpZQpuX29ic192YWxpZGFkYXMgPC0gY29udGFyX25fb2JzX3ZhbGlkYWRhcygpCm5fb2JzX3ZhbGlkYWRhcwpgYGAKCkZvcmFtIHNlbGVjaW9uYWRhcyBhcGVuYXMgYXMgb2JzZXJ2YcOnw7VlcyB2YWxpZGFkYXMgYW8gbsOtdmVsIGRlIGVzcMOpY2llLCBzb21hbmRvIHVtIHRvdGFsIGByIG5fb2JzX3ZhbGlkYWRhc1sxXWAgb2JzZXJ2YcOnw7Vlcy4KCmBgYHtyfQojIGdlcmFyIGdyw6FmaWNvIGNvbSBuw7ptZXJvIG9ic2VydmHDp8O1ZXMgdmFsaWRhZGFzIHBhcmEgY2FkYSBuw612ZWwgdGF4b27DtG1pY28KcGxvdGFyX25fb2JzX3ZhbGlkYWRhc19pbnRlcmF0aXZvKCkKYGBgCgpGaW5hbG1lbnRlIGNoZWdhbW9zIGFvIHN1YmNvbmp1bnRvIGRvcyBkYWRvcyBxdWUgc2Vyw6EgdXRpbGl6YWRvIHBhcmEKc2VsZWNpb25hciBxdWFpcyBlc3DDqWNpZXMgc2Vyw6NvIGFuYWxpc2FkYXMuCgpgYGB7cn0KIyBnZXJhciB0YWJlbGEgZGUgZGFkb3Mgc2VsZWNpb25hZG9zCmRhZG9zX3NlbGVjaW9uYWRvcyA8LSBjYXJyZWdhcl9kYWRvc19zZWxlY2lvbmFkb3MoKQoKIyBnZXJhciB0YWJkaW4gZGFkb3Nfc2VsZWNpb25hZG9zIApnZXJhcl90YWJkaW5fZGFkb3Nfc2VsZWNpb25hZG9zKCkKYGBgCgojIyMjICoqUXVhbnRhcyB1bmlkYWRlcyBkZSBjb25zZXJ2YcOnw6NvIGFvIHRvZG8/KioKCmBgYHtyIG5fZGVfdWNzfQojIGNvbnRhciBuw7ptZXJvIHRvdGFsIGRlIFVDJ3MgCm5fdWNzIDwtIGNvbnRhcl9uX3VjKCkKbl91Y3MKYGBgCgpPcyBkYWRvcyBzw6NvIHByb3ZlbmllbnRlcyBkZSBgciBuX3Vjc2AgdW5pZGFkZXMgZGUgY29uc2VydmHDp8OjbyBhbyB0b2RvLgoKIyMjIyAqKlF1YW50YXMgZXNww6ljaWVzIGFvIHRvZG8/KioKCmBgYHtyfQpuX3NwIDwtIGNvbnRhcl9uX3NwKCkKbl9zcApgYGAKCkF0w6kgYXF1aSB0ZW1vcyBkYWRvcyBwYXJhIGByIG5fc3BgIGVzcMOpY2llcy4KCiMjIyMgKipRdWFudGFzIG9ic2VydmHDp8O1ZXMgcG9yIHVuaWRhZGUgZGUgY29uc2VydmHDp8OjbyBhbyB0b2RvPyoqCgpgYGB7cn0KIyBjb250YXIgbsO6bWVybyBkZSBvYnNlcnZhw6fDtWVzIHBvciBVQwpuX29ic191YyA8LSBjb250YXJfbl9vYnNfdWMoKQoKIyBnZXJhciB0YWJkaW4KZ2VyYXJfdGFiZGluX25fb2JzX3VjKCkKYGBgCgoKYGBge3IsIGZpZy5oZWlnaHQ9MjAsIGZpZy5hbGlnbj0nY2VudGVyJ30KIyBwbG90YXIgbyBuw7ptZXJvIGRlIG9ic2VydmHDp8O1ZXMgcG9yIFVDCnBsb3Rhcl9uX29ic191Y19pbnRlcmF0aXZvKCkKYGBgCgojIyMjICoqUXVhbnRhcyBvYnNlcnZhw6fDtWVzIHBhcmEgY2FkYSBlc3DDqWNpZT8qKgoKYGBge3IsIGZpZy5oZWlnaHQ9MjB9CiMgY29udGFyIHRvdGFsIHNwCm5fb2JzX3NwIDwtIGNvbnRhcl9uX29ic19zcCgpCm5fb2JzX3NwCmBgYAoKYGBge3J9CiMgZ2VyYXIgdGFiZWxhIGRpbsOibWljYSBjb20gbyBuw7ptZXJvIHRvdGFsIGRlIG9ic2V2YcOnw7VlcyBwb3IgZXNww6ljaWUKZ2VyYXJfdGFiZGluX25fb2JzX3NwKCkKYGBgCgpgYGB7ciwgZmlnLmhlaWdodD0yMH0KIyBwbG90YXIgbyBvIG7Dum1lcm8gZGUgb2JzZXJ2YcOnw7VlcyBwb3IgVUMKcGxvdGFyX25fb2JzX3NwX2ludGVyYXRpdm8oKQpgYGAKClRhYmVsYSBpbnRlcmF0aXZhIHBhcmEgY29uc3VsdGEgZG8gbsO6bWVybyBkZSBvYnNlcnZhw6fDtWVzIHBvciBlc3DDqWNpZS4KCmBgYHtyfQpnZXJhcl90YWJkaW5fbl9vYnNfc3AoKQpgYGAKCiMjIyMgKipRdWFpcyBlIHF1YW50YXMgb2JzZXJ2YcOnw7VlcyBwYXJhIGNhZGEgZXNww6ljaWUgcG9yIHVuaWRhZGVzIGRlIGNvbnNlcnZhw6fDo28/KioKCmBgYHtyfQojIGdlcmFyIHRhYmVsYSBjb20gbyBuw7ptZXJvIGRlIG9ic2VydmHDp8O1ZXMgcG9yIGVzcMOpY2llIGUgcG9yIFVDCm5fb2JzX3NwX3VjIDwtIGNvbnRhcl9uX29ic19zcF91YygpCm5fb2JzX3NwX3VjCmBgYAoKCmBgYHtyfQpnZXJhcl90YWJkaW5fbl9vYnNfc3BfdWMoKQpgYGAKCiMjIyMgKipRdWFudGFzIHVuaWRhZGVzIGRlIGNvbnNlcnZhw6fDo28gZm9yYW0gYW1vc3RyYWRhcyBlbSBjYWRhIGFubz8qKgoKYGBge3IsIGVjaG89RkFMU0V9CiMgZ2VyYXIgdGFiZWxhIGNvbSBvIG7Dum1lcm8gZGUgdW5pZGFkZXMgZGUgY29uc2VydmHDp8OjbyBhbW9zdHJhZGFzIGVtIGNhZGEgYW5vCm5fdWNzX2FubyA8LSBjb250YXJfbl91Y19hbm8oKQpuX3Vjc19hbm8KYGBgCgpHZXJhciBmdW7Dp8OjbyBwYXJhIHRhYmVsYSBkaW7Dom1pY2EuCgpgYGB7cn0KZ2VyYXJfdGFiZGluX25fdWNfYW5vKCkKYGBgCgojIyMjICoqUXVhaXMgdW5pZGFkZXMgZGUgY29uc2VydmHDp8OjbyBmb3JhbSBhbW9zdHJhZGFzIGVtIHVtIG1haW9yIG7Dum1lcm8gZGUgYW5vcz8qKgoKYGBge3J9Cm5fYW5vX3VjIDwtIGNvbnRhcl9uX2Fub191YygpCm5fYW5vX3VjICAKYGBgCgpgYGB7cn0KZ2VyYXJfdGFiZGluX25fYW5vX3VjKCkKYGBgCgojIyMjICoqUXVhbnRhcyBvYnNlcnZhw6fDtWVzIGZvcmFtIHJlYWxpemFkYXMgcG9yIFVDIGVtIGNhZGEgYW5vPyoqCgpgYGB7cn0Kbl9vYnNfdWNfYW5vIDwtIGNvbnRhcl9uX29ic191Y19hbm8oKQpuX29ic191Y19hbm8KYGBgCgpUYWJlbGEgaW50ZXJhdGl2YSBwYXJhIGNvbnN1bHRhciBxdWFudGFzIG9ic2VydmHDp8O1ZXMgZm9yYW0gcmVhbGl6YWRhcwpwb3IgYW5vIGVtIGNhZGEgVUMKCmBgYHtyfQpnZXJhcl90YWJkaW5fbl9vYnNfdWNfYW5vKCkKYGBgCgojIyMjICoqUXVhbnRhcyBvYnNlcnZhw6fDtWVzIHBhcmEgY2FkYSBlc3DDqWNpZXMgcG9yIGFubz8qKgoKYGBge3J9Cm5fb2JzX3NwX2FubyA8LSBjb250YXJfbl9vYnNfc3BfYW5vKCkKbl9vYnNfc3BfYW5vCmBgYAoKVGFiZWxhIGludGVyYXRpdmEgcGFyYSBjb25zdWx0YXIgcXVhbnRhcyBvYnNlcnZhw6fDtWVzIGZvcmFtIHJlYWxpemFkYXMKcGFyYSBjYWRhIGVzcMOpY2llIGVtIGNhZGEgYW5vCgpgYGB7cn0KZ2VyYXJfdGFiZGluX25fb2JzX3NwX2FubygpCmBgYAoKIyMjIyAqKlF1YW50YXMgb2JzZXJ2YcOnw7VlcyBwYXJhIGNhZGEgZXNww6ljaWVzIHBvciBVQyBlIHBvciBhbm8/KioKCmBgYHtyfQpuX29ic19zcF91Y19hbm8gPC0gY29udGFyX25fb2JzX3NwX3VjX2FubygpCm5fb2JzX3NwX3VjX2FubwpgYGAKClRhYmVsYSBpbnRlcmF0aXZhIHBhcmEgY29uc3VsdGFyIHF1YW50YXMgb2JzZXJ2YcOnw7VlcyBmb3JhbSByZWFsaXphZGFzCnBhcmEgY2FkYSBlc3DDqWNpZSBlbSBjYWRhIGFubwoKYGBge3J9CmdlcmFyX3RhYmRpbl9uX29ic19zcF91Y19hbm8oKQpgYGAKCiMjIyMgKipRdWFudGFzIG9ic2VydmHDp8O1ZXMgcGFyYSBjYWRhIGVzcMOpY2llcyBwb3IgVUMsIHBvciBlc3Rhw6fDo28gZSBwb3IgYW5vPyoqCgpgYGB7cn0Kbl9vYnNfc3BfdWNfZXN0YWNhb19hbm8gPC0gY29udGFyX25fb2JzX3NwX3VjX2VzdGFjYW9fYW5vKCkKbl9vYnNfc3BfdWNfZXN0YWNhb19hbm8KYGBgCgpgYGB7cn0KZ2VyYXJfdGFiZGluX25fb2JzX3NwX3VjX2VzdGFjYW9fYW5vKCkKYGBgCgojIyMjICoqQXZhbGlhbmRvIG7Dum1lcm8gZGUgcsOpcGxpY2FzIChFc3Rhw6fDtWVzIEFtb3N0cmFpcykgcG9yIFVDKioKCiMjIyMgKipTZWxlY2lvbmFuZG8gbWVsaG9yZXMgbW9kZWxvcyBkZSBlc3R1ZG8gY29uc2lkZXJhbmRvIGVzdHJhdGlmaWNhw6fDo28gZXNwYWNpYWwvdGVtcG9yYWwgLS0gc2UgaMOhIHN1ZmljacOqbmNpYSBhbW9zdHJhbCAoNjAtODAgb2JzZXJ2YcOnw7VlcykgcG9yIGVzdHJhdG8qKgoKLSAgIFBvc3PDrXZlaXMgZXN0cmF0aWZpY2HDp8O1ZXMgZXNwYWNpYWlzCgotIEVBcy9VQ3MKCi0gVUNzL0VzcMOpY2llcwoKLSBQb3Nzw612ZWlzIGVzdHJhdGlmaWNhw6fDtWVzIHRlbXBvcmFpcwoKLSBFc3DDqWNpZS9VQy9Bbm8KCiMjIyMgKipBdmFsaWFuZG8gZGlzdMOibmNpYSBkZSB0cnVuY2FtZW50byoqCgotICAgR3LDoWZpY29zIGRlIGRpc3RyaWJ1acOnw6NvIGRhcyBmcmVxdcOqbmNpYXMgZGUgb2NvcnLDqm5jaWEgeCBkaXN0w6JuY2lhIHBlcnBlbmRpY3VsYXIuCgojIyMjICoqRGlzdHJpYnVpw6fDo28gZGUgZGlzdMOibmNpYXMqKgoKYGBge3IgZGlzdHJpYnVpY2FvX2RzaXRhbmNpYSwgd2FybmluZz1GQUxTRX0KIyBnZXJhciBvIGdyw6FmaWNvIGV4cGxvcmF0w7NyaW8gZGEgZGlzdHJpYnVpw6fDo28gZGUgZGlzdMOibmNpYXMgcGVycGVuZGljdWxhcmVzIHBhcmEgYSBlc3DDqWNpZXMgRGFzeXJvY3RhIGNyb2Nvbm90YSBuYSBSZXNleCBUYXBhasOzcy1BcmFwaXVucwpmaWcgPC0gZGFkb3NfZmlsdHJhZG9zIHw+CiAgIyBleGNsdWlyIE5BJ3MgZGEgdmFyacOhdmVsIGRpc3RhbmNlCiAgdGlkeXI6OmRyb3BfbmEoZGlzdGFuY2UpIHw+IAogIHBsb3Rhcl9kaXN0cmlidWljYW9fZGlzdGFuY2lhX2ludGVyYXRpdm8oKQoKZmlnCmBgYAoKIyMjIyAqKkF2YWxpYW5kbyBjb3ZhcmnDoXZlaXMqKgoKQXMgY292YXJpw6F2ZWlzIGRldmVtIHNlciBwZW5zYWRhcyBkZSBhY29yZG8gY29tIG8gZ3J1cG8gdGF4b27DtG1pY28uCkVzcMOpY2llcyBxdWUgZm9ybWFtIGdydXBvcyBkZXZlbSB0ZXIgYSBjb3ZhcmnDoXZlbCAnc2l6ZScuIEFzIGVzdHJhdMOpZ2lhcyBkZSBlc3RyYXRpZmljYcOnw6NvIHBvZGVtIHNlciBzdWJzdGl0dcOtZGFzIHBvciBjb3ZhcmnDoXZlaXMKdGFtYsOpbSAoZXN0cmF0b3MgZXNwYWNpYWlzLyBhbm8pLiBDb21vIGNvdmFyacOhdmVsIHRlbXBvcmFsLCBwb2RlIHNlIHBlbnNhciBlbSB1c2FyLCBhbMOpbSBkbyBhbm8sIGEgZXN0YcOnw6NvIGRvIGFubyAoc2Vhc29uKSwgbyBob3LDoXJpbyBkbyBkaWEgKHBhcmEgYW5pbWFpcyBxdWUgdmFyaWFtIGEgYXRpdmlkYWRlKS4gTyBob3LDoXJpbyBkbyBkaWEgcG9kZSBzZXIgY29udmVydGlkbyBlbSB0ZW1wbyBhcMOzcyBuYXNjZXIgZG8gc29sIChjb21vIG5vIGV4ZW1wbG8pLiBNYXMgcGFyYSBpc3NvIMOpIG5lY2Vzc8OhcmlvIGNyaWFyIGVzc2EgdmFyacOhdmVsIG5vIGRhdGFzZXQuIEUgbsOjbyDDqSB0cml2aWFsIHBvcnF1ZSBwcmVjaXNhIHNhYmVyIG8gaG9yw6FyaW8gZGUgbmFzY2VyIGRvIHNvbCBlbSBjYWRhIGRpYS9sb2NhbCBwYXJhIGNhbGN1bGFyLgoKIyAqKlBBUlRFIFYgLS0gQWp1c3RhbmRvIG9zIG1vZGVsb3MqKgoKIyMgRmx1eG8gZGUgYW7DoWxpc2UgZG9zIGRhZG9zOgoKQSBzZWd1aXIsIGFwcmVzZW50YW1vcyBvIGZsdXhvIGRlIGFuw6FsaXNlIGRvcyBkYWRvcyBxdWUgZW52b2x2ZSBhIGZhc2UgZXhwbG9yYXTDs3JpYSwgdHJ1bmNhbWVudG8sIGFqdXN0ZSBlIGF2YWxpYcOnw6NvIGRlIG1vZGVsb3MgZSBlc3RpbWF0aXZhcyBkZSBhYnVuZMOibmNpYSBlIGRlbnNpZGFkZSBwYXJhIGFzIGVzcMOpY2llcyBxdWUgc2VsZWNpb25hbW9zIGNvbW8gbW9kZWxvLiBVc2Ftb3MgY29tbyBjcml0w6lyaW9zIGRlIHNlbGXDp8OjbyB0YW50byBvIG7Dum1lcm8gZGUgb2NvcnLDqm5jaWFzIHBvciBVbmlkYWRlIGRlIENvbnNlcnZhw6fDo28gcXVhbnRvIGEgZGlzdHJpYnVpw6fDo28gZGFzIGZyZXF1w6puY2lhcyBkZSBvYnNlcnZhw6fDo28sIG5vcyBjYXNvcyBlbSBxdWUgaXNzbyBmb2kgcG9zc8OtdmVsLiBEZSBmb3JtYSBnZXJhbCwgYXMgZXNww6ljaWVzIGNvbSBuw7ptZXJvIHNhdGlzZmF0w7NyaW8gZGUgb2NvcnLDqm5jaWFzIChcPjYwKSwgYXByZXNlbnRhcmFtIHBpY28gZGUgb2JzZXJ2YcOnw7VlcyBwcsOzeGltb3MgYSB6ZXJvLgoKTsOzcyB1c2Ftb3MgY29tbyBtb2RlbG8gcGFyYSBlc3RlIGZsdXhvIERhc3lwcm9jdGEgY3JvY29ub3RhIGRhIFJlc2V4IFRhcGFqw7NzLUFyYXBpdW5zLCBwZWxvIGdyYW5kZSBuw7ptZXJvIGRlIG9jb3Jyw6puY2lhcyBwYXJhIHVtYSBtZXNtYSBVQy4gTsOzcyBpbXBsZW1lbnRhbW9zIGR1YXMgZXN0cmF0w6lnaWFzIHBhcmEgbGlkYXIgY29tIG9zIGVmZWl0b3MgaW5kZXNlamFkb3Mgbm9zIGRhZG9zOiBwaWNvIHByw7N4aW1vIGEgemVybyAoKmhlYXBpbmcgbmVhciB6ZXJvKikgZSBuw7ptZXJvIGV4Y2Vzc2l2byBkZSByZXBldGnDp8O1ZXMgYW1vc3RyYWlzIG5hIG1lc21hIHRyaWxoYS4gUGFyYSBsaWRhciBjb20gb3MgcGljb3MsIHRlc3RhbW9zIG8gdXNvIGRvcyBkYWRvcyBjb20gZGlzdMOibmNpYXMgZXhhdGFzIGUgZGlzdMOibmNpYXMgYWdydXBhZGFzLiBQYXJhIGxpZGFyIGNvbSBhcyByZXBldGnDp8O1ZXMsIHRlc3RhbW9zIGEgYW7DoWxpc2UgZG9zIGRhZG9zIGNvbSB0b2RhcyBhcyByZXBldGnDp8O1ZXMgZSBjb20gbyBuw7ptZXJvIGRlIHJlcGV0acOnw7VlcyByZWR1emlkYXMuIEVzc2FzIGVzdHJhdMOpZ2lhcyBlc3TDo28gZGVzY3JpdGFzIGVtIEZsdXhvcyAxLTMuIE5vIHByaW1lcm8gZmx1eG8sIGNvbWVudGFtb3MgdGFtYsOpbSBhcyBlc2NvbGhhcyBmZWl0YXMgZSBvcyByZXN1bHRhZG9zIG9idGlkb3MuIE9zIGRlbWFpcyBmbHV4b3Mgc8OjbyByZXBldGnDp8O1ZXMgZGVzdGUgcHJpbWVpcm8gZmx1eG8sIHBvcsOpbSBjb20gbXVkYW7Dp2EgbmEgZXN0cnV0dXJhIGRvcyBkYWRvcy4KCkVzcGVjaWVzIGNvbSBtYWlvciBudW1lcm8gZGUgb2NvcnJlbmNpYXMvVUMgcG9zc2liaWxpdGFtIHRlc3RhciwgcG9zdGVyaW9ybWVudGUsIGVzdHJhdGlmaWNhw6fDtWVzIG5vcyBkYWRvcywgcHJlc2VydmFuZG8gdW0gbsO6bWVybyBkZSBvY29ycsOqbmNpYXMgc2F0aXNmYXTDs3JpbyBkZW50cm8gZG9zIGVzdHJhdG9zLiBQb3IgaXNzbyBjb21lw6dhbW9zIGFwcmVzZW50YW5kbyB1bSBmbHV4byBjb21wbGV0byBkZSBhbsOhbGlzZSwgaW5jbHVpbmRvIEFtb3N0cmFnZW0gcG9yIERpc3TDom5jaWEgQ29udmVuY2lvbmFsLCBBbW9zdHJhZ2VtIHBvciBEaXN0w6JuY2lhIGNvbSBNw7psdGlwbGFzIENvdmFyacOhdmVpcyBlIEFtb3N0cmFnZW0gcG9yIERpc3TDom5jaWEgY29tIEVzdHJhdGlmaWNhw6fDo28gbm9zIGRhZG9zIGNvbSBhcyBlc3DDqWNpZXMgY29tIG1haW9yIG7Dum1lcm8gZGUgb2NvcnLDqm5jaWEuCgojIyBFc3DDqWNpZSBNb2RlbG8gLSBEYXN5cHJvY3RhIGNyb2Nvbm90YSAtIFJlc2V4IFRhcGFqw7NzIEFyYXBpdW5zCgohW0ZvbnRlOiBiaW9saWIuY3pdKGh0dHBzOi8vd3d3LmJpb2xpYi5jei9JTUcvR0FML0JJRy8yMDU4NDkuanBnKQoKRXNzYSDDqSBhIGVzcMOpY2llIGNvbSBvIG1haXIgbsO6bWVybyBkZSBvY29ycsOqbmNpYXMgcGFyYSB1bWEgbWVzbWEgVUMuIEFwcmVzZW50b3UsIGNvbW8gYSBtYWlvcmlhIGRhcyBlc3DDqWNpZXMgZW0gZGlmZXJlbnRlcyBVQ3MsIHVtIHBpY28gZGUgb2NvcnLDqm5jaWFzIHByw7N4aW1vIGEgemVyby4KCiMjIyBDYXJyZWdhciBEYWRvcwoKUGFyYSBzZWxlY2lvbmFyIGRvIGNvbmp1bnRvIGRlIGRhZG9zIGRhIGVzcMOpY2llIGUgYSBVbmlkYWRlIGRlIGNvbnNlcnZhw6fDo28gZGUgaW50ZXJlc3NlLCB1c2FyIGEgZnVuw6fDo28gYHRyYW5zZm9ybWFfcGFyYV9kaXN0YW5jZVJfY29tX3JlcGV0aWNhb19maWx0cmFfdWNfc3AoKWAsIGVzcGVjaWZpY2FuZG8gbyBub21lIGRhIFVuaWRhZGUgZGUgY29uc2VydmHDp8OjbyBhdHJhdsOpcyBkbyBhcmd1bWVudG8gYG5vbWVfdWNgIGUgbyBub21lIGRhIGVzcMOpY2llIGF0cmF2w6lzIGRvIGFyZ3VtZW50byBgbm9tZV9zcGAuCgpgYGB7cn0KIyBjYXJyZWdhciBkYWRvcwpjdXRpYV90YXBfYXJhcCA8LSB0cmFuc2Zvcm1hX3BhcmFfZGlzdGFuY2VSX2NvbV9yZXBldGljYW9fZmlsdHJhX3VjX3NwKAogIG5vbWVfdWMgPSAiUmVzZXggVGFwYWpvcy1BcmFwaXVucyIsCiAgbm9tZV9zcCA9ICJEYXN5cHJvY3RhIGNyb2Nvbm90YSIKKSAKCmN1dGlhX3RhcF9hcmFwCmBgYAoKIyMjIEFtb3N0cmFnZW0gcG9yIERpc3TDom5jaWEgQ29udmVuY2lvbmFsCgojIyMjIEZsdXhvIDEgLSBEaXN0w6JuY2lhcyBleGF0YXMgY29tIHRvZGFzIGFzIHJlcGV0acOnw7VlcwoKIyMjIyMgUGxvdGFuZG8gbyBoaXN0b2dyYW1hIGRhcyBmcmVxdcOqbmNpYXMgZGUgb2NvcnLDqm5jaWEgcGVsYSBkaXN0w6JuY2lhCgpPIGhpc3RvZ3JhbWEgaW50ZXJhdGl2byBlc3TDoSBkaXNwb27DrXZlbCBubyBhcHAgZW0gU2hpbnkgYGFwcF9kaXN0YW5jaWFfaW50ZXJhdGl2by5SYC4gQSBkaXN0cmlidWnDp8OjbyBkb3MgZGFkb3Mgbm8gaGlzdG9ncmFtYSBwZXJtaXRlIG9ic2VydmFyIHVtIHBpY28gZGUgb2JzZXJ2YcOnw7VlcyBwcsOzeGltbyBhIHplcm8sIGFsw6ltIGRlIHVtYSBjb25zaWRlcsOhdmVsIHBlcmRhIGVtIGRldGVjdGFiaWxpZGFkZSBhIHBhcnRpciBkb3MgMjBtLiBWYW1vcyB0ZXN0YXIgZGlmZXJlbnRlcyBwcm9wb3LDp8O1ZXMgZGUgdHJ1bmNhbWVudG8uIMOJIHBvc3PDrXZlbCBhbHRlcmFyIGEgYmluYWdlbSBkb3MgaGlzdG9ncmFtYXMgYXRyYXbDqXMgZG8gYXJndW1lbnRvIGBsYXJndXJhX2NhaXhhYC4gTmVzdGUgZXhlbXBsbyBhanVzdGFtb3MgcGFyYSAxLCBvIHF1ZSBmYWNpbGl0YSBhIG9ic2VydmHDp8OjbyBkZSBwaWNvcyBkZSBkZXRlY2HDp8OjbyBlIGVmZWl0b3MgZGUgKmhlYXBpbmcqIG5vcyBkYWRvcy4KCmBgYHtyLCBmaWcuaGVpZ2h0PTE1LCBmaWcud2lkdGg9MTB9CmN1dGlhX3RhcF9hcmFwIHw+IAogIGRyb3BfbmEoZGlzdGFuY2UpIHw+IApwbG90YXJfZGlzdHJpYnVpY2FvX2Rpc3RhbmNpYV9pbnRlcmF0aXZvKGxhcmd1cmFfY2FpeGEgPSAxKQpgYGAKCiMjIyMjIFRlc3RhbmRvIGRpc3TDom5jaWEgZGUgdHJ1bmNhbWVudG8gKCp3KikKClZhbW9zIGV4cGxvcmFyIGRpZmVyZW50ZXMgZGlzdMOibmNpYXMgZGUgdHJ1bmNhbWVudG8gcGFyYSB1bSBtZXNtbyBtb2RlbG8gZGUgZGlzdHJpYnVpw6fDo28gaGFsZi1ub3JtYWwuIE9wdGFtb3MgcG9yIHRydW5jYXIgb3MgZGFkb3MgcGVsYSBwZXJjZW50YWdlbSBwYXJhIHBhZHJvbml6YXIgYSByb3RpbmEgcGFyYSBkaWZlcmVudGVzIGVzcMOpY2llcy4gQnVja2xhbmQgZXQgYWwuICgyMDAxKSBzdWdlcmUgdW0gY29ydGUgZW50cmUgNS0xMCUgZGFzIG9ic2VydmHDp8O1ZXMgZGV0ZWN0YWRhcyBuYXMgbWFpb3JlcyBkaXN0w6NuY2lhcy4gVmFtb3Mgc2VsZWNpb25hciBvIHZhbG9yIGRlIGNvcnRlIHBlbG8gbW9kZWxvIGNvbSBtZWxob3IgYWp1c3RlLiBQYXJhIG9zIGRhZG9zLCB0ZXN0YW1vcyBhcyBzZWd1aW50ZXMgcHJvcG9yw6fDtWVzIGRlIGNvcnRlIGRlIGRhZG9zOiA1LCAxMCwgMTUsIDIwIGUgMjUlIGRhcyBvYnNlcnZhw6fDtWVzIG1haXMgZGlzdGFudGVzLiBHZXJhbW9zIHVtYSB0YWJlbGEgY29tcGFyYW5kbyBvcyBtb2RlbG9zIGUgdGFtYsOpbSBwbG90YW1vcyBvcyBncsOhZmljb3MgZG9zIG1vZGVsb3MgYWp1c3RhZG9zIHBhcmEgb3MgZGFkb3MgdHJ1bmNhZG9zLgoKIyMjIyMjIFRhYmVsYSBjb20gcmVzdW1vIGNvbXBhcmF0aXZvIGRvcyBtb2RlbG9zCgpgYGB7cn0KIyBjb25kdXogYSBzZWxlY2FvIGRhIG1lbGhvciBkaXN0YW5jaWEgZGUgdHJ1bmNhbWVudG8gYSBwYXJ0aXIgZG8gYWpzdXRlIGRlIG1vZGVsb3MgY29tIGZ1bmNhbyBkZSBkZXRlY2NhbyBoYWxmLW5vcm1hbCBzZW0gdGVybW9zIGRlIGFqdXN0ZQpjdXRpYV90YXBfYXJhcF9kaXN0X3RydW5jIDwtIGN1dGlhX3RhcF9hcmFwIHw+IAogIHNlbGVjaW9uYXJfZGlzdGFuY2lhX3RydW5jYW1lbnRvKCkKCmN1dGlhX3RhcF9hcmFwX2Rpc3RfdHJ1bmMkc2VsZWNhbwpgYGAKCiMjIyMjIyBQbG90YW5kbyBvIGhpc3RvZ3JhbWEgY29tIG9zIGRhZG9zIHRydW5jYWRvcy4KCkhpc3RvZ3JhbWFzIHJlc3VsdGFudGVzIGRvcyBtb2RlbG9zLCBjb20gdG9kYXMgYXMgZGlzdMOibmNpYXMgZGUgdHJ1bmNhZ2VtLCBwYXJhIGF1eGlsaWFyIG5hIHNlbGXDp8OjbyBkYSBtZWxob3IgZGlzdMOjbmNpYS4KCmBgYHtyfQpwbG90YXJfZnVuY2FvX2RldGVjY2FvX3NlbGVjYW9fZGlzdGFuY2lhX3RydW5jYW1lbnRvKGN1dGlhX3RhcF9hcmFwX2Rpc3RfdHJ1bmMpCmBgYAoKQXDDs3MgYXZhbGlhciB0YW50byBvIGFqdXN0ZSBkb3MgbW9kZWxvcyBxdWFudG8gb3MgZ3LDoWZpY29zLCBvcHRhbW9zIHBvciB0cnVuY2FyIDE1JSBkYXMgb2JzZXJ2YcOnw7VlcyBmZWl0YXMgbmFzIG1haW9yZXMgZGlzdMOibmNpYXMuIEFwZXNhciBkb3MgbWVsaG9yZXMgdmFsb3JlcyBkZSBBSUMgZSBkZSBhanVzdGUgZG8gQ3JhbcOpci12b24gTWlzZXMgcGFyYSAyNSUsIG9zIGhpc3RvZ3JhbWFzIGNvbSBtb2RlbG9zIGFqdXN0YWRvcyBwYXJhIDI1JSwgMjAlIGUgMTUlIGFwcmVzZW50YXJhbSBtb2RlbG9zIHF1YXNlIGxpbmVhcmVzIGUgY29tIHVtYSBncmFuZGUgcHJvYmFiaWxpZGFkZSBkZSBkZXRlw6fDo28gbm9zIMO6bHRpbW9zIGludGVydmFsb3MgZGUgZGlzdMOibmNpYS4gTyBtb2RlbG8gY29tIGNvcnRlIGRlIDEwJSBhcHJlc2VudG91IHVtYSBjdXJ2YSBkZWNyZXNjZW50ZSBlIG7Do28gdGVuZGV1IGEgemVybyBuYXMgw7psdGltYXMgZGlzdMOibmNpYXMuIErDoSBubyBtb2RlbG9zIHBhcmEgNSUgYXMgZnVuw6fDtWVzIGRlIGRldGXDp8OjbyB0ZW5kZW0gYSB6ZXJvIG5vcyDDumx0aW1vcyBpbnRlcnZhbG9zIGRlIGRpc3TDom5jaWEuIE8gY29ydGUgZGUgMTAlIGRhcyBvYnNlcnZhw6fDtWVzIG1haXMgZGlzdGFudGVzIHJlc3VsdG91IGVtIHVtYSBkaXN0w6JuY2lhIGRlIHRydW5jYW1lbnRvIGRlIDE1bS4KCiMjIyMjIEFqdXN0YW5kbyBkaWZlcmVudGVzIG1vZGVsb3MgZGUgZnVuw6fDtWVzIGRlIGRldGXDp8OjbwoKQXMgZnVuw6fDtWVzIGRlIGRldGXDp8OjbyBzw6NvIGFqdXN0YWRhcyBhdHJhdsOpcyBkYSBmdW7Dp8OjbyBgZHMoKWAgbm8gcGFjb3RlIERpc3RlbmNlIHBhcmEgbyBSLiBQYXJhIG90aW1pemFyIG8gZmx1eG8gZGUgYWp1c3RlIGRlIGZ1bsOnw7VlcywgZW1wYWNvdGFtb3MgYXMgZGlmZXJlbnRlcyBjb21iaW5hw6fDtWVzIGRlIGZ1bsOnw7VlcyBjaGF2ZSBlIHRlcm1vcyBkZSBhanVzdGVzIGVtIHRyw6pzIGZ1bsOnw7Vlcy4gU8OjbyBlbGFzOiBgYWp1c3RlX21vZGVsb3NfZGlzdGFuY2VfdW5pZigpYCwgcGFyYSBkaXN0cmlidWnDp8OjbyB1bmlmb3JtZSBzZW0gdGVybW9zIGRlIGFqdXN0ZSBlIGNvbSB0ZXJtb3MgZGUgYWp1c3RlIGRvIHRpcG8gY29zc2VubyBlIHBvbGlub21pYWwgc2ltcGxlcywgYGFqdXN0ZV9tb2RlbG9zX2Rpc3RhbmNlX2huKClgIHBhcmEgZGlzdHJpYnVpw6fDo28gaGFsZi1ub3JtYWwgc2VtIHRlcm1vcyBkZSBhanVzdGUgZSBjb20gdGVybW9zIGRlIGFqdXN0ZSBkbyB0aXBvIGNvc3Nlbm8gZSBwb2xpbm9taWFsIGRlIGhlcm1pdGU7IGUgYGFqdXN0ZV9tb2RlbG9zX2Rpc3RhbmNlX2hyKClgIHBhcmEgZGlzdHJpYnVpw6fDo28gaGF6YXJkLXJhdGUgc2VtIHRlcm1vcyBkZSBhanVzdGUgZSBjb20gdGVybW9zIGRlIGFqdXN0ZSBkbyB0aXBvIGNvc3Nlbm8gZSBwb2xpbm9taWFsIHNpbXBsZXMuIFBhcmEgZGVmaW5pciBhIGRpc3TDom5jaWEgZGUgdHJ1bmNhbWVudG8gZG9zIGRhZG9zIMOpIG5lY2Vzc8OhcmlvIGZvcm5lY2VyIG8gYXJndW1lbnRvIGB0cnVuY2FtZW50b2AsIHF1ZSBwb2RlIHNlciBkZWZpbmlkbyB0YW50byBlbSBwZXJjZW50YWdlbSBkZSBjb3J0ZSBkb3MgZGFkb3MgcXVhbnRvIGVtIHZhbG9yIGRlIGRpc3TDo25jaWEuCgojIyMjIyMgVW5pZm9ybWUgY29tIHRlcm1vcyBkZSBhanVzdGUgQ29zc2VubyBlIHBvbGlub21pYWwgc2ltcGxlcwoKYGBge3J9CiMgYWp1c3RhbmRvIGEgZnVuw6fDo28gZGUgZGV0ZWPDp8OjbyB1bmlmb3JtZSBwYXJhIHVtIHRydW5jYW1lbnRvIGRlIDEwJSBkb3MgZGFkb3MKY3V0aWFfdGFwX2FyYXBfdW5pZiA8LSBjdXRpYV90YXBfYXJhcCB8PiAKICBhanVzdGVfbW9kZWxvc19kaXN0YW5jZV91bmlmKHRydW5jYW1lbnRvID0gIjEwJSIpCgpgYGAKCkRlbnRyZSBhcyBjb21iaW5hw6fDtWVzIGRlIHRlcm1vcyBkZSBhanVzdGVzIHBhcmEgYSBmdW7Dp8OjbyBjaGF2ZSBkZSBkaXN0cmlidWnDp8OjbyB1bmlmb3JtZSwgbyBEaXN0YW5jZSBzZWxlY2lvbm91IG8gbW9kZWxvIHVuaWZvcm1lIGNvbSBhanVzdGUgcG9saW5vbWlhbCBzaW1wbGVzLCBjb20gYXMgb3JkZW5zIDIsIDQgZSA2LiBFbGUgbWFudMOpbSBlc3NlIG1vZGVsbywgZSBkZXNjYXJ0YSBvcyBkZW1haXMuIE9zICpXYXJuaW5ncyogaW5kaWNhbmRvIHF1ZSBhIGZ1bsOnw6NvIGRlIGRldGVjw6fDo28gbsOjbyDDqSBlc3RyaXRhbWVudGUgbW9ub3TDtG5pY2EgYXZpc2FtIHF1ZSBvcyBkYWRvcyBuw6NvIGZvcmFtIGNvbnN0cmFuZ2lkb3MgcGFyYSBhIG1vbm90b25pY2lkYWRlLiBJc3NvIHBvcnF1ZSBvIHVzbyBkZSB0ZXJtb3MgZGUgYWp1c3RlcywgZXNwZWNpYWxtZW50ZSBkZSBvcmRlbnMgYWNpbWEgZGUgMiwgcG9kZW0gbGV2YXIgw6AgcGVyZGEgZGEgbW9ub3RvbmlkYWRlIChhIGN1cnZhIHBvZGUgc2UgdG9ybmFyIGNyZXNjZW50ZSBlbSBhbGd1bSBtb21lbnRvLCBvIHF1ZSBuw6NvIMOpIGRlc2VqYWRvKS4gw4kgcHJlY2lzbyBhdmFsaWFyIHNlIGEgZmFsYSBkZXNzZSBjb25zdHJhZ2ltZW50byBsZXZvdSBlZmV0aXZhbWVudGUgw6AgcGVyZGEgZGEgbW9ub3RvbmljaWRhZGUgYW8gb2xoYXIgb3MgZ3LDoWZpY29zIGRlIGFqdXN0ZSBkb3MgbW9kZWxvcy4KCiMjIyMjIyBIYWxmLU5vcm1hbCBzZW0gdGVybW9zIGRlIGFqdXN0ZSBlIGNvbSB0ZXJtb3MgZGUgYWp1c3RlIENvc3Nlbm8gZSBQb2xpbm9taWFsIGRlIEhlcm1pdGUKCmBgYHtyfQojIGFqdXN0YW5kbyBhIGZ1bsOnw6NvIGRlIGRldGVjw6fDo28gaGFsZi1ub3JtYWwgcGFyYSB1bSB0cnVuY2FtZW50byBkZSAxMCUgZG9zIGRhZG9zCmN1dGlhX3RhcF9hcmFwX2huIDwtIGN1dGlhX3RhcF9hcmFwIHw+IAogIGFqdXN0ZV9tb2RlbG9zX2Rpc3RhbmNlX2huKHRydW5jYW1lbnRvID0gIjEwJSIpCmBgYAoKTmVzdGUgY2FzbywgbyBtb2RlbG8gc2VsZWNpb25hZG8gcGVsbyBEaXN0YW5jZSBmb2kgbyBIYWxmLW5vcm1hbCBzZW0gbmVuaHVtIHRlcm1vIGRlIGFqdXN0ZS4KCiMjIyMjIyBIYXphcmQtcmF0ZSBzZW0gdGVybW9zIGRlIGFqdXN0ZSBlIGNvbSB0ZXJtb3MgZGUgYWp1c3RlIENvc3Nlbm8gZSBQb2xpbm9taWFsIGRlIEhlcm1pdGUKCmBgYHtyfQojIGFqdXN0YW5kbyBhIGZ1bsOnw6NvIGRlIGRldGVjw6fDo28gaGF6YXJkLXJhdGUgcGFyYSB1bSB0cnVuY2FtZW50byBkZSAxMCUgZG9zIGRhZG9zCmN1dGlhX3RhcF9hcmFwX2hyIDwtIGN1dGlhX3RhcF9hcmFwIHw+IAogIGFqdXN0ZV9tb2RlbG9zX2Rpc3RhbmNlX2hyKHRydW5jYW1lbnRvID0gIjEwJSIpCmBgYAoKQXF1aSBvIG1lbGhvciBtb2RlbG8gc2VsZWNpb25hZG8gcGVsbyBEaXN0YW5jZSBmb2kgbyBIYXphcmQtcmF0ZSBzZW0gb3MgdGVybW9zIGRlIGFqdXN0ZS4gTmVzc2UgY2FzbywgdGFtYsOpbSBow6EgdW0gKndhcm5pbmcqIHBhcmEgbyBwcm9ibGVtYSBuYSBkaXN0cmlidWnDp8OjbyBkb3MgZGFkb3MsIHF1ZSBhcHJlc2VudGFtIHVtIHBpY28gcHLDs3hpbW8gYSBkaXN0w6JuY2lhIHplcm8gZSBuw6NvIHPDo28gYmVtIGFqdXN0YWRvcyBwZWxvIGhhemFyZC1oYXRlLgoKIyMjIyMgQ29tcGFyYW5kbyBvcyBtb2RlbG9zCgpQYXJhIGNvbXBhcmFyIG9zIG1vZGVsb3Mgw6kgcHJlY2lzbyBhdmFsaWFyIHRyw6pzIGNyaXTDqXJpb3M6IEFJQywgYWp1c3RlIGUgZm9ybWEgZGFzIGZ1bsOnw7VlcyBub3MgZ3LDoWZpY29zIGUgYm9uZGFkZSBkZSBhanVzdGUuIE8gcGFjb3RlIGRpc3RhbmNlIHBvc3N1aSBhIGZ1bsOnw6NvIGBzdW1tYXJpemVfZHNfbW9kZWxzYHF1ZSBnZXJhIHVtYSB0YWJlbGEgY29tIG9zIG1vZGVsb3MgcGFyYSBjb21wYXJhw6fDo28gZGUgYWxndW5zIHBhcsOibWV0cm9zOiBhIHByaW1laXJhIGNvbHVuYSAqKk1vZGVsKiosIGluZGljYSBhcyBmdW7Dp8O1ZXMgY2hhdmVzIGUgcmVzcGVjdGl2b3MgdGVybW9zIGRlIGFqdXN0ZTsgYSBjb2x1bmEgKipGb3JtdWxhKiogYXByZXNlbnRhIGFzIGNvdmFyacOhdmVpcywgcXVhbmRvIGluY2x1w61kYXMgbm8gbW9kZWxvLCBvdSBcfjEsIHF1YW5kbyBuw6NvIGjDoSBjb3ZhcmnDoXZlaXM7ICoqQy12TSBwLXZhbHVlKiogdmFpIGFwcmVzZW50YXIgb3MgdmFsb3JlcyBkZSBwIHBhcmEgbyB0ZXN0ZSBkZSBib25kYWRlIGRlIGFqdXN0ZSBkZSBDcmFtw6lyLXZvbiBNaXNlczsgJFxoYXR7UF9hfSQgYXByZXNlbnRhIGEgcHJvYmFsaWRhZGUgZGUgZGV0ZcOnw6NvIGdsb2JhbCBlc3RpbWFkYSBwYXJhIGNhZGEgbW9kZWxvOyAqKnNlKCoqJFxoYXR7UF9hfSQpIGFwcmVzZW50YSBvIGVycm8gcGFkcsOjbyBwYXJhIGFzIGVzdGltYXRpdmFzIGRlIHByb2JhYmlsaWRhZGUgZGUgZGV0ZWPDp8OjbzsgZSAkXERlbHRhJEFJQyBhcHJlc2VudGEgb3MgdmFsb3JlcyBkZSBkZWx0YSBBSUMuCgojIyMjIyMgVGFiZWxhIGNvbSBvIHJlc3VtbyBjb21wYXJhdGl2byBkb3MgbW9kZWxvcwoKYGBge3J9CmZsdXhvMV9saXN0YV9tb2RlbG9zX2FqdXN0YWRvcyA8LSBsaXN0KAogIGBoYWxmLW5vcm1hbGAgPSBjdXRpYV90YXBfYXJhcF9obiwgCiAgYGhhemFyZC1yYXRlYCA9IGN1dGlhX3RhcF9hcmFwX2hyLCAKICBgdW5pZm9ybWVgID0gY3V0aWFfdGFwX2FyYXBfdW5pZgopCgpmbHV4bzFfc2VsZWNhb19mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlIDwtIHNlbGVjaW9uYXJfZnVuY2FvX2RldGVjY2FvX3Rlcm1vX2FqdXN0ZShmbHV4bzFfbGlzdGFfbW9kZWxvc19hanVzdGFkb3MpCgpmbHV4bzFfc2VsZWNhb19mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlCmBgYAoKRGVudHJlIG9zIG1vZGVsb3MgdGVzdGFkb3MsIG8gcXVlIGFwcmVzZW50b3UgbWVsaG9yIHZhbG9yIGRlIGFqdXN0ZSBlIEFJQyBmb2kgbyBoYXphcmQtcmF0ZS4gTyBhanVzdGUgZG8gQ3JhbcOpci12b24gTWlzZXMgZm9pIGNvbnNpZGVyYXZlbG1lbnRlIG1haW9yIHF1ZSBvcyBkZW1haXMgKHBhcmEgZXNzZSB0aXBvIGRlIHRlc3RlLCBxdWFudG8gbWFpb3IgbyB2YWxvciBkZSBwLCBtZWxob3IgbyBhanVzdGUpLCBhc3NpbSBjb21vIGFzIGRpZmVyZW7Dp2FzIG5vIGRlbHRhIEFJQyBmb3JhbSBiYXN0YW50ZSBlbGV2YWRhcy4KCiMjIyMjIyBHcsOhZmljb3MgZGUgYWp1c3RlIGRhcyBmdW7Dp8O1ZXMgZGUgZGV0ZcOnw6NvIMOgcyBwcm9iYWJpbGlkYWRlcyBkZSBkZXRlw6fDo28KCmBgYHtyfQojIGdlcmFyIHVtYSBsaXN0YSBjb20gb3MgbW9kZWxvcyBzZWxlY2lvbmFkb3Mgb3JkZW5hZG9zIGRvIG1lbGhvciBwYXJhIG8gcGlvciBtb2RlbG8KZmx1eG8xX21vZGVsb3Nfc2VsZWNpb25hZG9zIDwtIGxpc3QoCiAgY3V0aWFfdGFwX2FyYXBfaHIkYFNlbSB0ZXJtb2AsCiAgY3V0aWFfdGFwX2FyYXBfdW5pZiRgQ29zc2Vub2AsCiAgY3V0aWFfdGFwX2FyYXBfaG4kYENvc3Nlbm9gLAogIGN1dGlhX3RhcF9hcmFwX3VuaWYkYFBvbGlub21pYWwgc2ltcGxlc2AsCiAgY3V0aWFfdGFwX2FyYXBfaG4kYFNlbSB0ZXJtb2AKKQoKIyBhdHJpYnVpciBvIG5vbWUgZG9zIG1vZGVsb3MgYW9zIGl0ZW5zIGRhIGxpc3RhCgpuYW1lcyhmbHV4bzFfbW9kZWxvc19zZWxlY2lvbmFkb3MpIDwtIGZsdXhvMV9zZWxlY2FvX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUkTW9kZWwKCiMgcGxvdGFyIGEgcHJvYmFiaWxpZGFkZSBkZSBkZXRlY8Onw6NvIG9ic2VydmFkYSAoYmFycmFzKSBlIGEgZXNwZXJhZGEgKGxpbmhhcyBlIHBvbnRvcykKcGxvdGFyX2Z1bmNhb19kZXRlY2Nhb19tb2RlbG9zX3NlbGVjaW9uYWRvcyhmbHV4bzFfbW9kZWxvc19zZWxlY2lvbmFkb3MpCmBgYAoKT2xoYW5kbyBwYXJhIG9zIGhpc3RvZ3JhbWFzIGNvbSBtb2RlbG9zIGFqdXN0YWRvcywgw6kgcG9zc8OtdmVsIG9ic2VydmFyIG8gZWZlaXRvIGRvIGFjw7ptdWxvIGRlIG9ic2VydmHDp8O1ZXMgcHLDs3hpbW8gYSB6ZXJvLiBPIG1vZGVsbyBjb20gYSBmdW7Dp8OjbyBjaGF2ZSBoYXphcmQtaGF0ZSBzZW0gdGVybW9zIGRlIGFqdXN0ZSwgYXBlc2FyIGRlIHRlciBhcHJlc2VudGFkbyBvIG1lbGhvciB2YWxvciBkZSBhanVzdGUgcGVsbyBDcmFtw6lyLXZvbiBNaXNlcyBlIG8gbWVsaG9yIHZhbG9yIGRlIEFJQywgYXByZXNlbnRvdSBkb2lzIHByb2JsZW1hcy4gQXMgcHJvYmFsaWRhZGVzIGRlIGRldGXDp8OjbyBlc3RpbWFkYXMgcG9yIGludGV2YWxvIGRlIGRpc3TDom5jaWEgKGJhcnJhcyBjaW56YXMpLCBmaWNhcmFtIG11aXRvIGJhaXhhcy4gQWzDqW0gZGlzc28sIGEgY3VydmEgZGEgZnVuw6fDo28gZGUgZGV0ZcOnw6NvIGFwcmVzZW50YSBwaWNvIG5hIGRpc3TDom5jaWEgcHLDs3hpbWEgYSB6ZXJvLCBkZWNhaW5kbyByYXBpZGFtZW50ZSBlIHNlIGFwcm94aW1hbmRvIGRlIHplcm8gYW8gbG9uZ28gZG8gZWl4byBkYXMgZGlzdMOjbmNpYXMuIFRvZG9zIG9zIG91dHJvcyBxdWF0cm8gbW9kZWxvcyB0aXZlcmFtIGFqdXN0ZSBlIEFJQyBiYXN0YW50ZSBpbmZlcmlvcmVzIGFvIGhhemFyZC1oYXRlLiBFbnRyZXRhbnRvIGFzIGN1cnZhcyBlc3TDo28gcmVsYXRpdmFtZW50ZSBtZWxob3Jlcy4gQXMgY3VydmFzIGRvIHNlZ3VuZG8gZSB0ZXJjZWlybyBtb2RlbG8sIHVuaWZvcm1lIGNvbSBhanVzdGUgY29zc2VubyBlIGhhbGYtbm9ybWFsIGNvbSBhanVzdGUgY29zc2VubywgcmVzcGVjdGl2YW1lbnRlLCB0ZW5kZW0gw6AgcGVyZGEgZGUgbW9ub3RvbmljaWRhZGUuIEFzIGR1YXMgw7psdGltYXMgY3VydmFzLCBwYXJhIG9zIG1vZGVsb3MgdW5pZm9ybWUgY29tIGFqdXN0ZSBwb2xpbm9taWFsIHNpbXBsZXMgZSBoYWxmLW5vcm1hbCBzZW0gYWp1c3RlLCBuw6NvIHBlcmRlbSBhIG1vbm90b25pY2lkYWRlLiBEZSBmb3JtYSBnZXJhbCwgYXMgcHJvYmFiaWxpZGFkZXMgZGUgZGV0ZWPDp8OjbyBuw6NvIHTDqm0gdW0gYm9tIGFqdXN0ZSBhYmFpeG8gZGEgY3VydmEsIGUgbsOjbyBhcHJlc2VudGFtIHVtIGRlY2FpbWVudG8gZ3JhZHVhbCBjb20gYSBkaXN0w6JuY2lhLiBFc3NlcyBzw6NvIHByb2JsZW1hcyBpbmVyZW50ZXMgw6AgZGlzdHJpYnVpw6fDo28gZG9zIGRhZG9zLgoKIyMjIyMjIFRlc3RlIGRlIGJvbmRhZGUgZGUgYWp1c3RlIGRvcyBtb2RlbG9zIGUgUS1RIHBsb3RzCgpgYGB7cn0KYm9uZGFkZV9hanVzdGVfZmx1eG8xIDwtIHRlc3Rhcl9ib25kYWRlX2FqdXN0ZShmbHV4bzFfbW9kZWxvc19zZWxlY2lvbmFkb3MsIHBsb3QgPSBUUlVFKQpib25kYWRlX2FqdXN0ZV9mbHV4bzEKYGBgCgpBcXVpIHPDo28gZ2VyYWRvcyBRLVEgcGxvdHMgcXVlIHBlcm1pdGVtIGF2YWxpYXIgYSBxdWFsaWRhZGUgZG8gYWp1c3RlIGRvcyBtb2RlbG9zLiBFIHRhbWLDqW0gdW1hIHRhYmVsYSBjb20gb3MgcmVzdWx0YWRvcyBkbyBDYXJtw6lyLXZvbiBNaXNlcywgb25kZSBXIMOpIG8gdmFsb3IgZG8gdGVzdGUgZSBwIHNldSB2YWxvciBkZSBzaWduaWZpY8OibmNpYS4gTmVzc2UgY2FzbywgcXVhbnRvIG1haW9yIG8gdmFsb3IgZGUgcCwgbWVsaG9yIG8gYWp1c3RlIGRvIG1vZGVsby4KCiMjIyMjIEF2YWxpYW5kbyBhcyBlc3RpbWF0aXZhcyBkZSBBYnVuZMOibmNpYSBlIERlbnNpZGFkZQoKQXF1aSwgc8OjbyByZXN1bWlkb3Mgb3MgZGFkb3MgZGUgdGF4YSBkZSBlbmNvbnRybywgYWJ1bmTDom5jaWEgZSBkZW5zaWRhZGUgZW0gdHLDqnMgdGFiZWxhcy4KCiMjIyMjIyBDYXJhY3RlcsOtc3RpY2FzIGRhIMOhcmVhIGRlIGVzdHVkbyBlIGRhIHRheGEgZGUgZW5jb250cm8KCmBgYHtyfQojIGdlcmEgbGlzdGEgY29udGVuZG8gb3MgbW9kZWxvcyBzZWxlY2lvbmFkb3MgcGFyYSBjYWRhIGZ1bsOnw6NvIGRlIGRldGVjw6fDo28gZSB0ZXJtbyBkZSBhanVzdGUKZmx1eG8xX2xpc3RhX21vZGVsb3NfYWp1c3RhZG9zX3Rlcm1vcyA8LSBsaXN0KAogIGN1dGlhX3RhcF9hcmFwX2hyJGBTZW0gdGVybW9gLAogIGN1dGlhX3RhcF9hcmFwX2huJENvc3Nlbm8sCiAgY3V0aWFfdGFwX2FyYXBfdW5pZiRDb3NzZW5vLAogIGN1dGlhX3RhcF9hcmFwX3VuaWYkYFBvbGlub21pYWwgc2ltcGxlc2AsCiAgY3V0aWFfdGFwX2FyYXBfaG4kYFNlbSB0ZXJtb2AKKQoKIyDDoXJlYSBkZSBlc3R1ZG8sIHRhbWFuaG8gZGEgw6FyZWEgZGUgZXN0dWRvLCBhcmVhIGNvYmVydGEgcGVsbyBlc2ZvcsOnbyBhbW9zdHJhbCwgZXNmb3LDp28gYW1vc3RyYWwgZW0gbWV0cm9zLCBuw7ptZXJvIGRlIGRldGVjw6fDtWVzLCBuw7ptZXJvIGRlIHRyYW5zZWN0b3MgKGVhKSwgdGF4YSBkZSBlbmNvbnRybywgY29lZmljaWVudGUgZGUgdmFyaWHDp8OjbyBkYSB0YXhhIGRlIGVuY29udHJvICAKZmx1eG8xX2NhcmFjdGVyaXN0aWNhc19hcmVhX2VzdHVkb190YXhhX2VuY29udHJvIDwtIGZsdXhvMV9saXN0YV9tb2RlbG9zX2FqdXN0YWRvc190ZXJtb3MgfD4gCiAgZ2VyYXJfY2FyYWN0ZXJpc3RpY2FzX2FyZWFfZXN0dWRvX3RheGFfZW5jb250cm8ocmVzdWx0YWRvX3NlbGVjYW9fbW9kZWxvcyA9IGZsdXhvMV9zZWxlY2FvX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUpCgpmbHV4bzFfY2FyYWN0ZXJpc3RpY2FzX2FyZWFfZXN0dWRvX3RheGFfZW5jb250cm8KYGBgCgojIyMjIyMgQ2FyYWN0ZXLDrXN0aWNhcyBkZSBhYnVuZMOibmNpYSwgZXNmb3LDp28gZSBkZXRlY8Onw6NvCgpgYGB7cn0KIyDDoXJlYSBkZSBlc3R1ZG8sIHRhbWFuaG8gZGEgw6FyZWEgZGUgZXN0dWRvLCB0cmlsaGFzIG91IGVzdGHDp8O1ZXMgYW1vc3RyYWlzLCBlc2ZvcsOnbyB0b3RhbCBlbSBjYWRhIHRyaWxoYSwgYWJ1bmTDom5jaWEgZXN0aW1hZGEgZW0gY2FkYSBlc3Rhw6fDo28gYW1vc3RyYWwsIG7Dum1lcm8gZGUgZGV0ZWPDp8O1ZXMgZW0gY2FkYSBlc3Rhw6fDo28gYW1vc3RyYWwsIMOhcmVhIHRvdGFsIGFtb3N0cmFkYQpmbHV4bzFfY2FyYWN0ZXJpc3RpY2FzX2VzZm9yY29fYWJ1bmRhbmNpYV9kZXRlY2NhbyA8LSBmbHV4bzFfbGlzdGFfbW9kZWxvc19hanVzdGFkb3NfdGVybW9zIHw+IAogIGdlcmFyX2NhcmFjdGVyaXN0aWNhc19lc2ZvcmNvX2FidW5kYW5jaWFfZGV0ZWNjYW8ocmVzdWx0YWRvX3NlbGVjYW9fbW9kZWxvcyA9IGZsdXhvMV9zZWxlY2FvX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUpCgpmbHV4bzFfY2FyYWN0ZXJpc3RpY2FzX2VzZm9yY29fYWJ1bmRhbmNpYV9kZXRlY2NhbwpgYGAKCiMjIyMjIyBDYXJhY3RlcsOtc3RpY2FzIGRlIGRlbnNpZGFkZQoKYGBge3J9CiMgdG90YWwsIGRlbnNpZGFkZSBlc3RpbWFkYSwgZXJybyBwYWRyw6NvIGRhIGRlbnNpZGFkZSBkZXN0aW1hZGEsIGNvZWZpY2llbnRlIGRlIHZhcmlhw6fDo28gZGEgZGVuc2lkYWRlIGRlc3RpbWFkYSwgaW50ZXJ2YWxvIGRlIGNvbmZpYW7Dp2EgaW5mZXJpb3IgZSBzdXBlcmlvciBkbyBjb2VmaWNpZW50ZSBkZSB2YXJpYcOnw6NvLCBncnVhcyBkZSBsaWJlcmRhZGUKZmx1eG8xX2NhcmFjdGVyaXN0aWNhc19kZW5zaWRhZGUgPC0gZmx1eG8xX2xpc3RhX21vZGVsb3NfYWp1c3RhZG9zX3Rlcm1vcyB8PiAKICBnZXJhcl9jYXJhY3RlcmlzdGljYXNfZGVuc2lkYWRlKHJlc3VsdGFkb19zZWxlY2FvX21vZGVsb3MgPSBmbHV4bzFfc2VsZWNhb19mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlKQoKZmx1eG8xX2NhcmFjdGVyaXN0aWNhc19kZW5zaWRhZGUKYGBgCgojIyMjIEZsdXhvIDIgLSBEaXN0w6JuY2lhcyBleGF0YXMgY29tIHJlcGV0acOnw7VlcyByZWR1emlkYXMKCiMjIyMjIEZpbHRyYW5kbyBvcyBkYWRvcyBwYXJhIHJlZHV6aXIgYXMgcmVwZXRpw6fDtWVzCgpgYGB7cn0KZGFkb3Nfc2VsZWNpb25hZG9zIDwtIGNhcnJlZ2FyX2RhZG9zX3NlbGVjaW9uYWRvcygpCmN1dGlhX3RhcF9hcmFwX3F1YXNlX3NlbV9yZXBldGljYW8gPC0gdHJhbnNmb3JtYV9wYXJhX2RzaXRhbmNlUl9xdWFzZV9zZW1fcmVwZXRpY2FvX2ZpbHRyYV91Y19zcF9jb3ZhcmlhdmVsKAogIGRhZG9zID0gZGFkb3Nfc2VsZWNpb25hZG9zLAogIG5vbWVfdWMgPSAiUmVzZXggVGFwYWpvcy1BcmFwaXVucyIsCiAgbm9tZV9zcCA9ICJEYXN5cHJvY3RhIGNyb2Nvbm90YSIKKQoKY3V0aWFfdGFwX2FyYXBfcXVhc2Vfc2VtX3JlcGV0aWNhbwpgYGAKCiMjIyMjIFBsb3RhbmRvIG8gaGlzdG9ncmFtYSBkYXMgZnJlcXXDqm5jaWFzIGRlIG9jb3Jyw6puY2lhIHBlbGEgZGlzdMOibmNpYQoKYGBge3IsIGZpZy5oZWlnaHQ9MTUsIGZpZy53aWR0aD0xMH0KY3V0aWFfdGFwX2FyYXBfcXVhc2Vfc2VtX3JlcGV0aWNhbyB8PiAKICBkcm9wX25hKGRpc3RhbmNlKSB8PiAKcGxvdGFyX2Rpc3RyaWJ1aWNhb19kaXN0YW5jaWFfaW50ZXJhdGl2byhsYXJndXJhX2NhaXhhID0gMSkKYGBgCgojIyMjIyBUZXN0YW5kbyBkaXN0w6JuY2lhIGRlIHRydW5jYW1lbnRvICgqdyopCgojIyMjIyMgVGFiZWxhIGNvbSByZXN1bW8gY29tcGFyYXRpdm8gZG9zIG1vZGVsb3MKCmBgYHtyfQojIGNvbmR1eiBhIHNlbGVjYW8gZGEgbWVsaG9yIGRpc3RhbmNpYSBkZSB0cnVuY2FtZW50byBhIHBhcnRpciBkbyBhanN1dGUgZGUgbW9kZWxvcyBjb20gZnVuY2FvIGRlIGRldGVjY2FvIGhhbGYtbm9ybWFsIHNlbSB0ZXJtb3MgZGUgYWp1c3RlCmN1dGlhX3RhcF9hcmFwX3F1YXNlX3NlbV9yZXBldGljYW9fZGlzdF90cnVuYyA8LSBjdXRpYV90YXBfYXJhcF9xdWFzZV9zZW1fcmVwZXRpY2FvIHw+IAogIHNlbGVjaW9uYXJfZGlzdGFuY2lhX3RydW5jYW1lbnRvKCkKCmN1dGlhX3RhcF9hcmFwX3F1YXNlX3NlbV9yZXBldGljYW9fZGlzdF90cnVuYyRzZWxlY2FvCmBgYAoKIyMjIyMjIFBsb3RhbmRvIG8gaGlzdG9ncmFtYSBjb20gb3MgZGFkb3MgdHJ1bmNhZG9zLgoKYGBge3J9CnBsb3Rhcl9mdW5jYW9fZGV0ZWNjYW9fc2VsZWNhb19kaXN0YW5jaWFfdHJ1bmNhbWVudG8oY3V0aWFfdGFwX2FyYXBfcXVhc2Vfc2VtX3JlcGV0aWNhb19kaXN0X3RydW5jKQoKYGBgCgojIyMjIyBBanVzdGFuZG8gZGlmZXJlbnRlcyBtb2RlbG9zIGRlIGZ1bsOnw7VlcyBkZSBkZXRlw6fDo28KCiMjIyMjIyBVbmlmb3JtZSArIENvc3Nlbm8KCmBgYHtyfQojIGFqdXN0YW5kbyBhIGZ1bsOnw6NvIGRlIGRldGVjw6fDo28gdW5pZm9ybWUgcGFyYSB1bSB0cnVuY2FtZW50byBkZSAxMCUgZG9zIGRhZG9zCmN1dGlhX3RhcF9hcmFwX3F1YXNlX3NlbV9yZXBldGljYW9fdW5pZiA8LSBjdXRpYV90YXBfYXJhcF9xdWFzZV9zZW1fcmVwZXRpY2FvIHw+IAogIGFqdXN0ZV9tb2RlbG9zX2Rpc3RhbmNlX3VuaWYodHJ1bmNhbWVudG8gPSAiMTAlIikKCmBgYAoKIyMjIyMjIEhhbGYtTm9ybWFsIHNlbSB0ZXJtb3MgZGUgYWp1c3RlIGUgY29tIHRlcm1vcyBkZSBhanVzdGUKCmBgYHtyfQojIGFqdXN0YW5kbyBhIGZ1bsOnw6NvIGRlIGRldGVjw6fDo28gaGFsZi1ub3JtYWwgcGFyYSB1bSB0cnVuY2FtZW50byBkZSAxMCUgZG9zIGRhZG9zCmN1dGlhX3RhcF9hcmFwX3F1YXNlX3NlbV9yZXBldGljYW9faG4gPC0gY3V0aWFfdGFwX2FyYXBfcXVhc2Vfc2VtX3JlcGV0aWNhbyB8PiAKICBhanVzdGVfbW9kZWxvc19kaXN0YW5jZV9obih0cnVuY2FtZW50byA9ICIxMCUiKQpgYGAKCiMjIyMjIyBIYXphcmQtcmF0ZSBzZW0gdGVybW9zIGRlIGFqdXN0ZSBlIGNvbSB0ZXJtb3MgZGUgYWp1c3RlCgpgYGB7cn0KIyBhanVzdGFuZG8gYSBmdW7Dp8OjbyBkZSBkZXRlY8Onw6NvIGhhbGYtbm9ybWFsIHBhcmEgdW0gdHJ1bmNhbWVudG8gZGUgMTAlIGRvcyBkYWRvcwpjdXRpYV90YXBfYXJhcF9xdWFzZV9zZW1fcmVwZXRpY2FvX2hyIDwtIGN1dGlhX3RhcF9hcmFwX3F1YXNlX3NlbV9yZXBldGljYW8gfD4gCiAgYWp1c3RlX21vZGVsb3NfZGlzdGFuY2VfaHIodHJ1bmNhbWVudG8gPSAiMTAlIikKYGBgCgojIyMjIyBDb21wYXJhbmRvIG9zIG1vZGVsb3MKCiMjIyMjIyBUYWJlbGEgY29tIG8gcmVzdW1vIGNvbXBhcmF0aXZvIGRvcyBtb2RlbG9zCgpgYGB7cn0KZmx1eG8yX2xpc3RhX21vZGVsb3NfYWp1c3RhZG9zIDwtIGxpc3QoCiAgYGhhbGYtbm9ybWFsYCA9IGN1dGlhX3RhcF9hcmFwX3F1YXNlX3NlbV9yZXBldGljYW9faG4sIAogIGBoYXphcmQtcmF0ZWAgPSBjdXRpYV90YXBfYXJhcF9xdWFzZV9zZW1fcmVwZXRpY2FvX2hyLCAKICBgdW5pZm9ybWVgID0gY3V0aWFfdGFwX2FyYXBfcXVhc2Vfc2VtX3JlcGV0aWNhb191bmlmCikKCmZsdXhvMl9zZWxlY2FvX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUgPC0gc2VsZWNpb25hcl9mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlKGZsdXhvMl9saXN0YV9tb2RlbG9zX2FqdXN0YWRvcykKCmZsdXhvMl9zZWxlY2FvX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUKYGBgCiMjIyMjIyBHcsOhZmljb3MgZGUgYWp1c3RlIGRhcyBmdW7Dp8O1ZXMgZGUgZGV0ZcOnw6NvIMOgcyBwcm9iYWJpbGlkYWRlcyBkZSBkZXRlw6fDo28KCmBgYHtyfQojIGdlcmFyIHVtYSBsaXN0YSBjb20gb3MgbW9kZWxvcyBzZWxlY2lvbmFkb3Mgb3JkZW5hZG9zIGRvIG1lbGhvciBwYXJhIG8gcGlvciBtb2RlbG8KZmx1eG8yX21vZGVsb3Nfc2VsZWNpb25hZG9zIDwtIGxpc3QoCiAgY3V0aWFfdGFwX2FyYXBfcXVhc2Vfc2VtX3JlcGV0aWNhb19ociRgU2VtIHRlcm1vYCwKICBjdXRpYV90YXBfYXJhcF9xdWFzZV9zZW1fcmVwZXRpY2FvX2huJGBDb3NzZW5vYCwKICBjdXRpYV90YXBfYXJhcF9xdWFzZV9zZW1fcmVwZXRpY2FvX3VuaWYkYENvc3Nlbm9gLAogIGN1dGlhX3RhcF9hcmFwX3F1YXNlX3NlbV9yZXBldGljYW9fdW5pZiRgUG9saW5vbWlhbCBzaW1wbGVzYCwKICBjdXRpYV90YXBfYXJhcF9xdWFzZV9zZW1fcmVwZXRpY2FvX2huJGBTZW0gdGVybW9gCikKCiMgYXRyaWJ1aXIgbyBub21lIGRvcyBtb2RlbG9zIGFvcyBpdGVucyBkYSBsaXN0YQoKbmFtZXMoZmx1eG8yX21vZGVsb3Nfc2VsZWNpb25hZG9zKSA8LSBmbHV4bzJfc2VsZWNhb19mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlJE1vZGVsCgojIHBsb3RhciBhIHByb2JhYmlsaWRhZGUgZGUgZGV0ZWPDp8OjbyBvYnNlcnZhZGEgKGJhcnJhcykgZSBhIGVzcGVyYWRhIChsaW5oYXMgZSBwb250b3MpCnBsb3Rhcl9mdW5jYW9fZGV0ZWNjYW9fbW9kZWxvc19zZWxlY2lvbmFkb3MoZmx1eG8yX21vZGVsb3Nfc2VsZWNpb25hZG9zKQpgYGAKCiMjIyMjIyBUZXN0ZSBkZSBib25kYWRlIGRlIGFqdXN0ZSBkb3MgbW9kZWxvcyBlIFEtUSBwbG90cwoKYGBge3J9CmJvbmRhZGVfYWp1c3RlX2ZsdXhvMiA8LSB0ZXN0YXJfYm9uZGFkZV9hanVzdGUoZmx1eG8yX21vZGVsb3Nfc2VsZWNpb25hZG9zLCBwbG90ID0gVFJVRSkKYm9uZGFkZV9hanVzdGVfZmx1eG8yCmBgYAoKIyMjIyMgQXZhbGlhbmRvIGFzIGVzdGltYXRpdmFzIGRlIEFidW5kw6JuY2lhIGUgRGVuc2lkYWRlCgojIyMjIyMgQ2FyYWN0ZXLDrXN0aWNhcyBkYSDDoXJlYSBkZSBlc3R1ZG8gZSBkYSB0YXhhIGRlIGVuY29udHJvCgpgYGB7cn0KIyBnZXJhIGxpc3RhIGNvbnRlbmRvIG9zIG1vZGVsb3Mgc2VsZWNpb25hZG9zIHBhcmEgY2FkYSBmdW7Dp8OjbyBkZSBkZXRlY8Onw6NvIGUgdGVybW8gZGUgYWp1c3RlCmZsdXhvMl9saXN0YV9tb2RlbG9zX2FqdXN0YWRvc190ZXJtb3MgPC0gbGlzdCgKICBjdXRpYV90YXBfYXJhcF9xdWFzZV9zZW1fcmVwZXRpY2FvX2hyJGBTZW0gdGVybW9gLAogIGN1dGlhX3RhcF9hcmFwX3F1YXNlX3NlbV9yZXBldGljYW9faG4kYENvc3Nlbm9gLAogIGN1dGlhX3RhcF9hcmFwX3F1YXNlX3NlbV9yZXBldGljYW9fdW5pZiRgQ29zc2Vub2AsCiAgY3V0aWFfdGFwX2FyYXBfcXVhc2Vfc2VtX3JlcGV0aWNhb191bmlmJGBQb2xpbm9taWFsIHNpbXBsZXNgLAogIGN1dGlhX3RhcF9hcmFwX3F1YXNlX3NlbV9yZXBldGljYW9faG4kYFNlbSB0ZXJtb2AKKQoKIyDDoXJlYSBkZSBlc3R1ZG8sIHRhbWFuaG8gZGEgw6FyZWEgZGUgZXN0dWRvLCBhcmVhIGNvYmVydGEgcGVsbyBlc2ZvcsOnbyBhbW9zdHJhbCwgZXNmb3LDp28gYW1vc3RyYWwgZW0gbWV0cm9zLCBuw7ptZXJvIGRlIGRldGVjw6fDtWVzLCBuw7ptZXJvIGRlIHRyYW5zZWN0b3MgKGVhKSwgdGF4YSBkZSBlbmNvbnRybywgY29lZmljaWVudGUgZGUgdmFyaWHDp8OjbyBkYSB0YXhhIGRlIGVuY29udHJvICAKZmx1eG8yX2NhcmFjdGVyaXN0aWNhc19hcmVhX2VzdHVkb190YXhhX2VuY29udHJvIDwtIGZsdXhvMl9saXN0YV9tb2RlbG9zX2FqdXN0YWRvc190ZXJtb3MgfD4gCiAgZ2VyYXJfY2FyYWN0ZXJpc3RpY2FzX2FyZWFfZXN0dWRvX3RheGFfZW5jb250cm8ocmVzdWx0YWRvX3NlbGVjYW9fbW9kZWxvcyA9IGZsdXhvMl9zZWxlY2FvX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUpCgpmbHV4bzJfY2FyYWN0ZXJpc3RpY2FzX2FyZWFfZXN0dWRvX3RheGFfZW5jb250cm8KYGBgCgojIyMjIyMgQ2FyYWN0ZXLDrXN0aWNhcyBkZSBhYnVuZMOibmNpYSwgZXNmb3LDp28gZSBkZXRlY8Onw6NvCgoKYGBge3J9CiMgw6FyZWEgZGUgZXN0dWRvLCB0YW1hbmhvIGRhIMOhcmVhIGRlIGVzdHVkbywgdHJpbGhhcyBvdSBlc3Rhw6fDtWVzIGFtb3N0cmFpcywgZXNmb3LDp28gdG90YWwgZW0gY2FkYSB0cmlsaGEsIGFidW5kw6JuY2lhIGVzdGltYWRhIGVtIGNhZGEgZXN0YcOnw6NvIGFtb3N0cmFsLCBuw7ptZXJvIGRlIGRldGVjw6fDtWVzIGVtIGNhZGEgZXN0YcOnw6NvIGFtb3N0cmFsLCDDoXJlYSB0b3RhbCBhbW9zdHJhZGEKZmx1eG8yX2NhcmFjdGVyaXN0aWNhc19lc2ZvcmNvX2FidW5kYW5jaWFfZGV0ZWNjYW8gPC0gZmx1eG8yX2xpc3RhX21vZGVsb3NfYWp1c3RhZG9zX3Rlcm1vcyB8PiAKICBnZXJhcl9jYXJhY3RlcmlzdGljYXNfZXNmb3Jjb19hYnVuZGFuY2lhX2RldGVjY2FvKHJlc3VsdGFkb19zZWxlY2FvX21vZGVsb3MgPSBmbHV4bzJfc2VsZWNhb19mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlKQoKZmx1eG8yX2NhcmFjdGVyaXN0aWNhc19lc2ZvcmNvX2FidW5kYW5jaWFfZGV0ZWNjYW8KYGBgCgojIyMjIyMgQ2FyYWN0ZXLDrXN0aWNhcyBkZSBkZW5zaWRhZGUKCmBgYHtyfQojIHRvdGFsLCBkZW5zaWRhZGUgZXN0aW1hZGEsIGVycm8gcGFkcsOjbyBkYSBkZW5zaWRhZGUgZGVzdGltYWRhLCBjb2VmaWNpZW50ZSBkZSB2YXJpYcOnw6NvIGRhIGRlbnNpZGFkZSBkZXN0aW1hZGEsIGludGVydmFsbyBkZSBjb25maWFuw6dhIGluZmVyaW9yIGUgc3VwZXJpb3IgZG8gY29lZmljaWVudGUgZGUgdmFyaWHDp8OjbywgZ3J1YXMgZGUgbGliZXJkYWRlCmZsdXhvMl9jYXJhY3RlcmlzdGljYXNfZGVuc2lkYWRlIDwtIGZsdXhvMl9saXN0YV9tb2RlbG9zX2FqdXN0YWRvc190ZXJtb3MgfD4gCiAgZ2VyYXJfY2FyYWN0ZXJpc3RpY2FzX2RlbnNpZGFkZShyZXN1bHRhZG9fc2VsZWNhb19tb2RlbG9zID0gZmx1eG8yX3NlbGVjYW9fZnVuY2FvX2RldGVjY2FvX3Rlcm1vX2FqdXN0ZSkKCmZsdXhvMl9jYXJhY3RlcmlzdGljYXNfZGVuc2lkYWRlCmBgYAoKIyMjIyBGbHV4byAzIC0gRGlzdMOibmNpYXMgYWdydXBhZGFzIGNvbSB0b2RhcyBhcyByZXBldGnDp8O1ZXMKCkFxdWkgdmFtb3MgcGFydGlyIGRvIG1lc21vIGNvbmp1bnRvIGRlIGRhZG9zIGRvIEZsdXhvIDEgKGBjdXRpYV90YXBfYXJhcGApLCBjb20gdG9kYXMgYXMgcmVwZXRpw6fDtWVzLCBtYXMgdmFtb3MgYWdydXBhciBhcyBkaXN0w6JuY2lhcyBlbSBpbnRlcnZhbG9zLiBWYW1vcyB1c2FyIG8gbWVzbW8gdmFsb3IgZGUgdHJ1bmNhbWVudG8sIHJlbW92ZW5kbyAxMCUgZGFzIG9ic2VydmHDp8O1ZXMgbmFzIG1haW9yZXMgZGlzdMOibmNpYXMsIG8gcXVlIHNpZ25pZmljYSBxdWUgYXByb3ZlaXRhcmVtb3MgYXMgb2JzZXJ2YcOnw7VlcyBmZWl0YXMgYXTDqSAxNW0gZGUgZGlzdMOibmNpYSBkbyBvYnNlcnZhZG9yLgoKIyMjIyMgUGxvdGFuZG8gbyBoaXN0b2dyYW1hIGRhcyBmcmVxdcOqbmNpYXMgZGUgb2NvcnLDqm5jaWEgcGVsYSBkaXN0w6JuY2lhCgpPIGhpc3RvZ3JhbWEgaW50ZXJhdGl2byBlc3TDoSBkaXNwb27DrXZlbCBubyBhcHAgZW0gU2hpbnkgYGFwcF9kaXN0YW5jaWFfaW50ZXJhdGl2by5SYC4KCkFxdWksIHBsb3RhbW9zIHF1YXRybyBoaXN0b2dyYW1hcyBjb20gYmluYWdlbnMgZGlmZXJlbnRlcywgcGFyYSBvYnNlcnZhciBvIGVmZWl0byBkZSBhZ3J1cGFyIG9zIGRhZG9zIHNvYnJlIGFzIGRpc3RyaWJ1acOnw7VlcyBkYXMgZnJlcXXDqm5jaWFzIGRlIG9jb3Jyw6puY2lhIG5vcyBoaXN0b2dyYW1hcy4KCmBgYHtyLCBmaWcuaGVpZ2h0PTE1LCBmaWcud2lkdGg9MTB9CmN1dGlhX3RhcF9hcmFwIHw+IAogIGRyb3BfbmEoZGlzdGFuY2UpIHw+IApwbG90YXJfZGlzdHJpYnVpY2FvX2Rpc3RhbmNpYV9pbnRlcmF0aXZvKGxhcmd1cmFfY2FpeGEgPSAxKQoKY3V0aWFfdGFwX2FyYXAgfD4gCiAgZHJvcF9uYShkaXN0YW5jZSkgfD4gCnBsb3Rhcl9kaXN0cmlidWljYW9fZGlzdGFuY2lhX2ludGVyYXRpdm8obGFyZ3VyYV9jYWl4YSA9IDIpCgpjdXRpYV90YXBfYXJhcCB8PiAKICBkcm9wX25hKGRpc3RhbmNlKSB8PiAKcGxvdGFyX2Rpc3RyaWJ1aWNhb19kaXN0YW5jaWFfaW50ZXJhdGl2byhsYXJndXJhX2NhaXhhID0gMykKCmN1dGlhX3RhcF9hcmFwIHw+IAogIGRyb3BfbmEoZGlzdGFuY2UpIHw+IApwbG90YXJfZGlzdHJpYnVpY2FvX2Rpc3RhbmNpYV9pbnRlcmF0aXZvKGxhcmd1cmFfY2FpeGEgPSA1KQoKYGBgCgojIyMjIyBEZWZpbmluZG8gb3MgaW50ZXZhbG9zIGRlIGRpc3TDom5jaWEgZGUgYWdydXBhbWVudG8KCiMjIyMjIyBQcmltZWlyYSBiaW5hZ2VtIC0gSW50ZXJ2YWxvcyBpZ3VhaXMgZGUgMS41bQoKYGBge3J9CmN1dGlhX3RhcF9hcmFwX2JpbjEgPC0gY3JlYXRlX2JpbnMoCiAgY3V0aWFfdGFwX2FyYXBbIWlzLm5hKGN1dGlhX3RhcF9hcmFwJGRpc3RhbmNlKSxdLCAKICBjKDAsIDEuNSwgMywgNC41LCA2LCA3LjUsIDksIDEwLjUsIDEyLCAxMy41LCAxNSkKKQpgYGAKCiMjIyMjIyBTZWd1bmRhIGJpbmFnZW0gLSBQcmltZWlybyBpbnRlcnZhbG8gZGUgMW0gZSBkZW1haXMgaW50ZXJ2YWxvcyBkZSAxLjRtCgpgYGB7cn0KY3V0aWFfdGFwX2FyYXBfYmluMiA8LSBjcmVhdGVfYmlucygKICBjdXRpYV90YXBfYXJhcFshaXMubmEoY3V0aWFfdGFwX2FyYXAkZGlzdGFuY2UpLF0sIAogIGMoMCwgMSwgMi40LCAzLjgsIDUuMiwgNi42LCA4LCA5LjQsIDEwLjgsIDEyLjIsIDEzLjYsIDE1KQopCmBgYAoKIyMjIyMjIFRlcmNlaXJhIGJpbmFnZW0gLSBJbnRlcnZhbG9zIGlndWFpcyBkZSAyLjVtCgpgYGB7cn0KY3V0aWFfdGFwX2FyYXBfYmluMyA8LSBjcmVhdGVfYmlucygKICBjdXRpYV90YXBfYXJhcFshaXMubmEoY3V0aWFfdGFwX2FyYXAkZGlzdGFuY2UpLF0sIAogIGMoMCwgMi41LCA1LCA3LjUsIDEwLCAxMi41LCAxNSkKKQpgYGAKCiMjIyMjIEFqdXN0YW5kbyBkaWZlcmVudGVzIG1vZGVsb3MgZGUgZnVuw6fDtWVzIGRlIGRldGXDp8OjbwoKIyMjIyMjIFVuaWZvcm1lICsgQ29zc2VubwoKUHJpbWVpcmEgQmluYWdlbQoKYGBge3J9CgpjdXRpYV90YXBfYXJhcF9iaW4xX3VuaWYgPC0gY3V0aWFfdGFwX2FyYXBfYmluMSB8PiAKICBhanVzdGVfbW9kZWxvc19kaXN0YW5jZV91bmlmKHRydW5jYW1lbnRvID0gMTUpCgpgYGAKClNlZ3VuZGEgYmluYWdlbQoKYGBge3J9CgpjdXRpYV90YXBfYXJhcF9iaW4yX3VuaWYgPC0gY3V0aWFfdGFwX2FyYXBfYmluMiB8PiAKICBhanVzdGVfbW9kZWxvc19kaXN0YW5jZV91bmlmKHRydW5jYW1lbnRvID0gMTUpCgpgYGAKClRlcmNlaXJhIGJpbmFnZW0KCmBgYHtyfQoKY3V0aWFfdGFwX2FyYXBfYmluM191bmlmIDwtIGN1dGlhX3RhcF9hcmFwX2JpbjMgfD4gCiAgYWp1c3RlX21vZGVsb3NfZGlzdGFuY2VfdW5pZih0cnVuY2FtZW50byA9IDE1KQoKYGBgCgojIyMjIyMgSGFsZi1Ob3JtYWwgc2VtIHRlcm1vcyBkZSBhanVzdGUgZSBjb20gdGVybW9zIGRlIGFqdXN0ZQoKUHJpbWVpcmEgYmluYWdlbQoKYGBge3J9CgpjdXRpYV90YXBfYXJhcF9iaW4xX2huIDwtIGN1dGlhX3RhcF9hcmFwX2JpbjEgfD4gCiAgYWp1c3RlX21vZGVsb3NfZGlzdGFuY2VfaG4odHJ1bmNhbWVudG8gPSAxNSkKCmBgYAoKU2VndW5kYSBiaW5hZ2VtCgpgYGB7cn0KCmN1dGlhX3RhcF9hcmFwX2JpbjJfaG4gPC0gY3V0aWFfdGFwX2FyYXBfYmluMiB8PiAKICBhanVzdGVfbW9kZWxvc19kaXN0YW5jZV9obih0cnVuY2FtZW50byA9IDE1KQoKYGBgCgpUZXJjZWlyYSBiaW5hZ2VtCgpgYGB7cn0KCmN1dGlhX3RhcF9hcmFwX2JpbjNfaG4gPC0gY3V0aWFfdGFwX2FyYXBfYmluMyB8PiAKICBhanVzdGVfbW9kZWxvc19kaXN0YW5jZV9obih0cnVuY2FtZW50byA9IDE1KQoKYGBgCgojIyMjIyMgSGF6YXJkLXJhdGUgc2VtIHRlcm1vcyBkZSBhanVzdGUgZSBjb20gdGVybW9zIGRlIGFqdXN0ZQoKUHJpbWVpcmEgYmluYWdlbQoKYGBge3J9CgpjdXRpYV90YXBfYXJhcF9iaW4xX2hyIDwtIGN1dGlhX3RhcF9hcmFwX2JpbjEgfD4gCiAgYWp1c3RlX21vZGVsb3NfZGlzdGFuY2VfaHIodHJ1bmNhbWVudG8gPSAxNSkKCmBgYAoKU2VndW5kYSBiaW5hZ2VtCgpgYGB7cn0KCmN1dGlhX3RhcF9hcmFwX2JpbjJfaHIgPC0gY3V0aWFfdGFwX2FyYXBfYmluMiB8PiAKICBhanVzdGVfbW9kZWxvc19kaXN0YW5jZV9ocih0cnVuY2FtZW50byA9IDE1KQoKYGBgCgpUZXJjZWlyYSBiaW5hZ2VtCgpgYGB7cn0KCmN1dGlhX3RhcF9hcmFwX2JpbjNfaHIgPC0gY3V0aWFfdGFwX2FyYXBfYmluMyB8PiAKICBhanVzdGVfbW9kZWxvc19kaXN0YW5jZV9ocih0cnVuY2FtZW50byA9IDE1KQoKYGBgCgojIyMjIyBDb21wYXJhbmRvIG9zIG1vZGVsb3MKCiMjIyMjIyBUYWJlbGEgY29tIG8gcmVzdW1vIGNvbXBhcmF0aXZvIGRvcyBtb2RlbG9zCgpgYGB7cn0KZmx1eG8zLjFfbGlzdGFfbW9kZWxvc19hanVzdGFkb3MgPC0gbGlzdCgKICBgaGFsZi1ub3JtYWxgID0gY3V0aWFfdGFwX2FyYXBfYmluMV9obiwgCiAgYGhhemFyZC1yYXRlYCA9IGN1dGlhX3RhcF9hcmFwX2JpbjFfaHIsIAogIGB1bmlmb3JtZWAgPSBjdXRpYV90YXBfYXJhcF9iaW4xX3VuaWYKKQoKZmx1eG8zLjFfc2VsZWNhb19mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlIDwtIHNlbGVjaW9uYXJfZnVuY2FvX2RldGVjY2FvX3Rlcm1vX2FqdXN0ZShmbHV4bzMuMV9saXN0YV9tb2RlbG9zX2FqdXN0YWRvcykKCmZsdXhvMy4xX3NlbGVjYW9fZnVuY2FvX2RldGVjY2FvX3Rlcm1vX2FqdXN0ZQpgYGAKCmBgYHtyfQpmbHV4bzMuMl9saXN0YV9tb2RlbG9zX2FqdXN0YWRvcyA8LSBsaXN0KAogIGBoYWxmLW5vcm1hbGAgPSBjdXRpYV90YXBfYXJhcF9iaW4yX2huLCAKICBgaGF6YXJkLXJhdGVgID0gY3V0aWFfdGFwX2FyYXBfYmluMl9ociwgCiAgYHVuaWZvcm1lYCA9IGN1dGlhX3RhcF9hcmFwX2JpbjJfdW5pZgopCgpmbHV4bzMuMl9zZWxlY2FvX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUgPC0gc2VsZWNpb25hcl9mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlKGZsdXhvMy4yX2xpc3RhX21vZGVsb3NfYWp1c3RhZG9zKQoKZmx1eG8zLjJfc2VsZWNhb19mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlCmBgYAoKYGBge3J9CmZsdXhvMy4zX2xpc3RhX21vZGVsb3NfYWp1c3RhZG9zIDwtIGxpc3QoCiAgYGhhbGYtbm9ybWFsYCA9IGN1dGlhX3RhcF9hcmFwX2JpbjNfaG4sIAogIGBoYXphcmQtcmF0ZWAgPSBjdXRpYV90YXBfYXJhcF9iaW4zX2hyLCAKICBgdW5pZm9ybWVgID0gY3V0aWFfdGFwX2FyYXBfYmluM191bmlmCikKCmZsdXhvMy4zX3NlbGVjYW9fZnVuY2FvX2RldGVjY2FvX3Rlcm1vX2FqdXN0ZSA8LSBzZWxlY2lvbmFyX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUoZmx1eG8zLjNfbGlzdGFfbW9kZWxvc19hanVzdGFkb3MpCgpmbHV4bzMuM19zZWxlY2FvX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUKYGBgCgojIyMjIyMgR3LDoWZpY29zIGRlIGFqdXN0ZSBkYXMgZnVuw6fDtWVzIGRlIGRldGXDp8OjbyDDoHMgcHJvYmFiaWxpZGFkZXMgZGUgZGV0ZcOnw6NvCgpQcmltZWlyYSBiaW5hZ2VtCgpgYGB7cn0KZmx1eG8zLjFfbW9kZWxvc19zZWxlY2lvbmFkb3MgPC0gbGlzdCgKICBjdXRpYV90YXBfYXJhcF9iaW4xX2huJGBDb3NzZW5vYCwKICBjdXRpYV90YXBfYXJhcF9iaW4xX3VuaWYkYENvc3Nlbm9gLAogIGN1dGlhX3RhcF9hcmFwX2JpbjFfaHIkYFNlbSB0ZXJtb2AsCiAgY3V0aWFfdGFwX2FyYXBfYmluMV91bmlmJGBQb2xpbm9taWFsIHNpbXBsZXNgLAogIGN1dGlhX3RhcF9hcmFwX2JpbjFfaG4kYFNlbSB0ZXJtb2AKKQoKcGxvdGFyX2Z1bmNhb19kZXRlY2Nhb19tb2RlbG9zX3NlbGVjaW9uYWRvcyhmbHV4bzMuMV9tb2RlbG9zX3NlbGVjaW9uYWRvcykKYGBgCgpTZWd1bmRhIGJpbmFnZW0KCmBgYHtyfQpmbHV4bzMuMl9tb2RlbG9zX3NlbGVjaW9uYWRvcyA8LSBsaXN0KAogIGN1dGlhX3RhcF9hcmFwX2JpbjJfaG4kYENvc3Nlbm9gLAogIGN1dGlhX3RhcF9hcmFwX2JpbjJfaHIkYFNlbSB0ZXJtb2AsCiAgY3V0aWFfdGFwX2FyYXBfYmluMl91bmlmJGBDb3NzZW5vYCwKICBjdXRpYV90YXBfYXJhcF9iaW4yX3VuaWYkYFBvbGlub21pYWwgc2ltcGxlc2AsCiAgY3V0aWFfdGFwX2FyYXBfYmluMl9obiRgU2VtIHRlcm1vYAopCgpwbG90YXJfZnVuY2FvX2RldGVjY2FvX21vZGVsb3Nfc2VsZWNpb25hZG9zKGZsdXhvMy4yX21vZGVsb3Nfc2VsZWNpb25hZG9zKQpgYGAKClRlcmNlaXJhIGJpbmFnZW0KCmBgYHtyfQpmbHV4bzMuM19tb2RlbG9zX3NlbGVjaW9uYWRvcyA8LSBsaXN0KAogIGN1dGlhX3RhcF9hcmFwX2JpbjNfaG4kYENvc3Nlbm9gLAogIGN1dGlhX3RhcF9hcmFwX2JpbjNfaHIkYENvc3Nlbm9gLAogIGN1dGlhX3RhcF9hcmFwX2JpbjNfaHIkYFBvbGlub21pYWwgc2ltcGxlc2AsCiAgY3V0aWFfdGFwX2FyYXBfYmluM19ociRgU2VtIHRlcm1vYCwKICBjdXRpYV90YXBfYXJhcF9iaW4zX3VuaWYkYENvc3Nlbm9gLAogIGN1dGlhX3RhcF9hcmFwX2JpbjNfdW5pZiRgUG9saW5vbWlhbCBzaW1wbGVzYCwKICBjdXRpYV90YXBfYXJhcF9iaW4zX2huJGBTZW0gdGVybW9gCikKCnBsb3Rhcl9mdW5jYW9fZGV0ZWNjYW9fbW9kZWxvc19zZWxlY2lvbmFkb3MoZmx1eG8zLjNfbW9kZWxvc19zZWxlY2lvbmFkb3MpCmBgYAoKIyMjIyMjIFRlc3RlIGRlIGJvbmRhZGUgZGUgYWp1c3RlIGRvcyBtb2RlbG9zIGUgUS1RIHBsb3RzCgpBaW5kYSBlc3RhbW9zIGFqdXN0YW5kbyBvcyBvdXRwdXRzIHBhcmEgb3MgdGVzdGVzIGRlIGJvbmRhZGUsIHBvaXMgYSBiaW5hZ2VtIHVtIGNvbmZsaXRvIGNvbSBvIGZvcm1hdG8gZGUgdGFiZWxhIGRlZmluaWRvIHBlbGEgZnVuw6fDo28gb3JpZ2luYWwuCgpQcmltZWlyYSBiaW5hZ2VtCgpgYGB7ciwgcmVzdWx0cz0naGlkZSd9CmJvbmRhZGVfYWp1c3RlX2ZsdXhvMy4xIDwtIHRlc3Rhcl9ib25kYWRlX2FqdXN0ZShmbHV4bzMuMV9tb2RlbG9zX3NlbGVjaW9uYWRvcywgcGxvdCA9IFRSVUUsIGNoaXNxID0gVFJVRSwgYnJlYWtzID0gIGMoMCwgMS41LCAzLCA0LjUsIDYsIDcuNSwgOSwgMTAuNSwgMTIsIDEzLjUsIDE1KSkKYm9uZGFkZV9hanVzdGVfZmx1eG8zLjEKYGBgCgpTZWd1bmRhIGJpbmFnZW0KCmBgYHtyLCByZXN1bHRzPSdoaWRlJ30KYm9uZGFkZV9hanVzdGVfZmx1eG8zLjIgPC0gdGVzdGFyX2JvbmRhZGVfYWp1c3RlKGZsdXhvMy4yX21vZGVsb3Nfc2VsZWNpb25hZG9zKQpib25kYWRlX2FqdXN0ZV9mbHV4bzMuMgpgYGAKClRlcmNlaXJhIGJpbmFnZW0KCmBgYHtyLCByZXN1bHRzPSdoaWRlJ30KYm9uZGFkZV9hanVzdGVfZmx1eG8zLjMgPC0gdGVzdGFyX2JvbmRhZGVfYWp1c3RlKGZsdXhvMy4zX21vZGVsb3Nfc2VsZWNpb25hZG9zKQpib25kYWRlX2FqdXN0ZV9mbHV4bzMuMwpgYGAKCgojIyMjIyBBdmFsaWFuZG8gYXMgZXN0aW1hdGl2YXMgZGUgQWJ1bmTDom5jaWEgZSBEZW5zaWRhZGUKCiMjIyMjIyBDYXJhY3RlcsOtc3RpY2FzIGRhIMOhcmVhIGRlIGVzdHVkbyBlIGRhIHRheGEgZGUgZW5jb250cm8KClByaW1laXJhIGJpbmFnZW0KCmBgYHtyfQojIGdlcmEgbGlzdGEgY29udGVuZG8gb3MgbW9kZWxvcyBzZWxlY2lvbmFkb3MgcGFyYSBjYWRhIGZ1bsOnw6NvIGRlIGRldGVjw6fDo28gZSB0ZXJtbyBkZSBhanVzdGUKZmx1eG8zLjFfbGlzdGFfbW9kZWxvc19hanVzdGFkb3NfdGVybW9zIDwtIGxpc3QoCiAgY3V0aWFfdGFwX2FyYXBfYmluMV9obiRgQ29zc2Vub2AsCiAgY3V0aWFfdGFwX2FyYXBfYmluMV91bmlmJGBDb3NzZW5vYCwKICBjdXRpYV90YXBfYXJhcF9iaW4xX2hyJGBTZW0gdGVybW9gLAogIGN1dGlhX3RhcF9hcmFwX2JpbjFfdW5pZiRgUG9saW5vbWlhbCBzaW1wbGVzYCwKICBjdXRpYV90YXBfYXJhcF9iaW4xX2huJGBTZW0gdGVybW9gCikKCiMgw6FyZWEgZGUgZXN0dWRvLCB0YW1hbmhvIGRhIMOhcmVhIGRlIGVzdHVkbywgYXJlYSBjb2JlcnRhIHBlbG8gZXNmb3LDp28gYW1vc3RyYWwsIGVzZm9yw6dvIGFtb3N0cmFsIGVtIG1ldHJvcywgbsO6bWVybyBkZSBkZXRlY8Onw7VlcywgbsO6bWVybyBkZSB0cmFuc2VjdG9zIChlYSksIHRheGEgZGUgZW5jb250cm8sIGNvZWZpY2llbnRlIGRlIHZhcmlhw6fDo28gZGEgdGF4YSBkZSBlbmNvbnRybyAgCmZsdXhvMy4xX2NhcmFjdGVyaXN0aWNhc19hcmVhX2VzdHVkb190YXhhX2VuY29udHJvIDwtIGZsdXhvMy4xX2xpc3RhX21vZGVsb3NfYWp1c3RhZG9zX3Rlcm1vcyB8PiAKICBnZXJhcl9jYXJhY3RlcmlzdGljYXNfYXJlYV9lc3R1ZG9fdGF4YV9lbmNvbnRybyhyZXN1bHRhZG9fc2VsZWNhb19tb2RlbG9zID0gZmx1eG8zLjFfc2VsZWNhb19mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlKQoKZmx1eG8zLjFfY2FyYWN0ZXJpc3RpY2FzX2FyZWFfZXN0dWRvX3RheGFfZW5jb250cm8KYGBgCgpTZWd1bmRhIGJpbmFnZW0KCmBgYHtyfQojIGdlcmEgbGlzdGEgY29udGVuZG8gb3MgbW9kZWxvcyBzZWxlY2lvbmFkb3MgcGFyYSBjYWRhIGZ1bsOnw6NvIGRlIGRldGVjw6fDo28gZSB0ZXJtbyBkZSBhanVzdGUKZmx1eG8zLjJfbGlzdGFfbW9kZWxvc19hanVzdGFkb3NfdGVybW9zIDwtIGxpc3QoCiAgY3V0aWFfdGFwX2FyYXBfYmluMl9obiRgQ29zc2Vub2AsCiAgY3V0aWFfdGFwX2FyYXBfYmluMl9ociRgU2VtIHRlcm1vYCwKICBjdXRpYV90YXBfYXJhcF9iaW4yX3VuaWYkYENvc3Nlbm9gLAogIGN1dGlhX3RhcF9hcmFwX2JpbjJfdW5pZiRgUG9saW5vbWlhbCBzaW1wbGVzYCwKICBjdXRpYV90YXBfYXJhcF9iaW4yX2huJGBTZW0gdGVybW9gCikKCiMgw6FyZWEgZGUgZXN0dWRvLCB0YW1hbmhvIGRhIMOhcmVhIGRlIGVzdHVkbywgYXJlYSBjb2JlcnRhIHBlbG8gZXNmb3LDp28gYW1vc3RyYWwsIGVzZm9yw6dvIGFtb3N0cmFsIGVtIG1ldHJvcywgbsO6bWVybyBkZSBkZXRlY8Onw7VlcywgbsO6bWVybyBkZSB0cmFuc2VjdG9zIChlYSksIHRheGEgZGUgZW5jb250cm8sIGNvZWZpY2llbnRlIGRlIHZhcmlhw6fDo28gZGEgdGF4YSBkZSBlbmNvbnRybyAgCmZsdXhvMy4yX2NhcmFjdGVyaXN0aWNhc19hcmVhX2VzdHVkb190YXhhX2VuY29udHJvIDwtIGZsdXhvMy4yX2xpc3RhX21vZGVsb3NfYWp1c3RhZG9zX3Rlcm1vcyB8PiAKICBnZXJhcl9jYXJhY3RlcmlzdGljYXNfYXJlYV9lc3R1ZG9fdGF4YV9lbmNvbnRybyhyZXN1bHRhZG9fc2VsZWNhb19tb2RlbG9zID0gZmx1eG8zLjJfc2VsZWNhb19mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlKQoKZmx1eG8zLjJfY2FyYWN0ZXJpc3RpY2FzX2FyZWFfZXN0dWRvX3RheGFfZW5jb250cm8KYGBgCgpUZXJjZWlyYSBiaW5hZ2VtCgpgYGB7cn0KIyBnZXJhIGxpc3RhIGNvbnRlbmRvIG9zIG1vZGVsb3Mgc2VsZWNpb25hZG9zIHBhcmEgY2FkYSBmdW7Dp8OjbyBkZSBkZXRlY8Onw6NvIGUgdGVybW8gZGUgYWp1c3RlCmZsdXhvMy4zX2xpc3RhX21vZGVsb3NfYWp1c3RhZG9zX3Rlcm1vcyA8LSBsaXN0KAogIGN1dGlhX3RhcF9hcmFwX2JpbjNfaG4kYENvc3Nlbm9gLAogIGN1dGlhX3RhcF9hcmFwX2JpbjNfaHIkYENvc3Nlbm9gLAogIGN1dGlhX3RhcF9hcmFwX2JpbjNfaHIkYFBvbGlub21pYWwgc2ltcGxlc2AsCiAgY3V0aWFfdGFwX2FyYXBfYmluM19ociRgU2VtIHRlcm1vYCwKICBjdXRpYV90YXBfYXJhcF9iaW4zX3VuaWYkYENvc3Nlbm9gLAogIGN1dGlhX3RhcF9hcmFwX2JpbjNfdW5pZiRgUG9saW5vbWlhbCBzaW1wbGVzYCwKICBjdXRpYV90YXBfYXJhcF9iaW4zX2huJGBTZW0gdGVybW9gCikKCiMgw6FyZWEgZGUgZXN0dWRvLCB0YW1hbmhvIGRhIMOhcmVhIGRlIGVzdHVkbywgYXJlYSBjb2JlcnRhIHBlbG8gZXNmb3LDp28gYW1vc3RyYWwsIGVzZm9yw6dvIGFtb3N0cmFsIGVtIG1ldHJvcywgbsO6bWVybyBkZSBkZXRlY8Onw7VlcywgbsO6bWVybyBkZSB0cmFuc2VjdG9zIChlYSksIHRheGEgZGUgZW5jb250cm8sIGNvZWZpY2llbnRlIGRlIHZhcmlhw6fDo28gZGEgdGF4YSBkZSBlbmNvbnRybyAgCmZsdXhvMy4zX2NhcmFjdGVyaXN0aWNhc19hcmVhX2VzdHVkb190YXhhX2VuY29udHJvIDwtIGZsdXhvMy4zX2xpc3RhX21vZGVsb3NfYWp1c3RhZG9zX3Rlcm1vcyB8PiAKICBnZXJhcl9jYXJhY3RlcmlzdGljYXNfYXJlYV9lc3R1ZG9fdGF4YV9lbmNvbnRybyhyZXN1bHRhZG9fc2VsZWNhb19tb2RlbG9zID0gZmx1eG8zLjNfc2VsZWNhb19mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlKQoKZmx1eG8zLjNfY2FyYWN0ZXJpc3RpY2FzX2FyZWFfZXN0dWRvX3RheGFfZW5jb250cm8KYGBgCgoKCiMjIyMjIyBDYXJhY3RlcsOtc3RpY2FzIGRlIGFidW5kw6JuY2lhLCBlc2ZvcsOnbyBlIGRldGVjw6fDo28KClByaW1laXJhIGJpbmFnZW0KYGBge3J9CiMgw6FyZWEgZGUgZXN0dWRvLCB0YW1hbmhvIGRhIMOhcmVhIGRlIGVzdHVkbywgdHJpbGhhcyBvdSBlc3Rhw6fDtWVzIGFtb3N0cmFpcywgZXNmb3LDp28gdG90YWwgZW0gY2FkYSB0cmlsaGEsIGFidW5kw6JuY2lhIGVzdGltYWRhIGVtIGNhZGEgZXN0YcOnw6NvIGFtb3N0cmFsLCBuw7ptZXJvIGRlIGRldGVjw6fDtWVzIGVtIGNhZGEgZXN0YcOnw6NvIGFtb3N0cmFsLCDDoXJlYSB0b3RhbCBhbW9zdHJhZGEKZmx1eG8zLjFfY2FyYWN0ZXJpc3RpY2FzX2VzZm9yY29fYWJ1bmRhbmNpYV9kZXRlY2NhbyA8LSBmbHV4bzMuMV9saXN0YV9tb2RlbG9zX2FqdXN0YWRvc190ZXJtb3MgfD4gCiAgZ2VyYXJfY2FyYWN0ZXJpc3RpY2FzX2VzZm9yY29fYWJ1bmRhbmNpYV9kZXRlY2NhbyhyZXN1bHRhZG9fc2VsZWNhb19tb2RlbG9zID0gZmx1eG8zLjFfc2VsZWNhb19mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlKQoKZmx1eG8zLjFfY2FyYWN0ZXJpc3RpY2FzX2VzZm9yY29fYWJ1bmRhbmNpYV9kZXRlY2NhbwpgYGAKClNlZ3VuZGEgYmluYWdlbQpgYGB7cn0KIyDDoXJlYSBkZSBlc3R1ZG8sIHRhbWFuaG8gZGEgw6FyZWEgZGUgZXN0dWRvLCB0cmlsaGFzIG91IGVzdGHDp8O1ZXMgYW1vc3RyYWlzLCBlc2ZvcsOnbyB0b3RhbCBlbSBjYWRhIHRyaWxoYSwgYWJ1bmTDom5jaWEgZXN0aW1hZGEgZW0gY2FkYSBlc3Rhw6fDo28gYW1vc3RyYWwsIG7Dum1lcm8gZGUgZGV0ZWPDp8O1ZXMgZW0gY2FkYSBlc3Rhw6fDo28gYW1vc3RyYWwsIMOhcmVhIHRvdGFsIGFtb3N0cmFkYQpmbHV4bzMuMl9jYXJhY3RlcmlzdGljYXNfZXNmb3Jjb19hYnVuZGFuY2lhX2RldGVjY2FvIDwtIGZsdXhvMy4yX2xpc3RhX21vZGVsb3NfYWp1c3RhZG9zX3Rlcm1vcyB8PiAKICBnZXJhcl9jYXJhY3RlcmlzdGljYXNfZXNmb3Jjb19hYnVuZGFuY2lhX2RldGVjY2FvKHJlc3VsdGFkb19zZWxlY2FvX21vZGVsb3MgPSBmbHV4bzMuMl9zZWxlY2FvX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUpCgpmbHV4bzMuMl9jYXJhY3RlcmlzdGljYXNfZXNmb3Jjb19hYnVuZGFuY2lhX2RldGVjY2FvCmBgYAoKVGVyY2VpcmEgYmluYWdlbQpgYGB7cn0KIyDDoXJlYSBkZSBlc3R1ZG8sIHRhbWFuaG8gZGEgw6FyZWEgZGUgZXN0dWRvLCB0cmlsaGFzIG91IGVzdGHDp8O1ZXMgYW1vc3RyYWlzLCBlc2ZvcsOnbyB0b3RhbCBlbSBjYWRhIHRyaWxoYSwgYWJ1bmTDom5jaWEgZXN0aW1hZGEgZW0gY2FkYSBlc3Rhw6fDo28gYW1vc3RyYWwsIG7Dum1lcm8gZGUgZGV0ZWPDp8O1ZXMgZW0gY2FkYSBlc3Rhw6fDo28gYW1vc3RyYWwsIMOhcmVhIHRvdGFsIGFtb3N0cmFkYQpmbHV4bzMuM19jYXJhY3RlcmlzdGljYXNfZXNmb3Jjb19hYnVuZGFuY2lhX2RldGVjY2FvIDwtIGZsdXhvMy4zX2xpc3RhX21vZGVsb3NfYWp1c3RhZG9zX3Rlcm1vcyB8PiAKICBnZXJhcl9jYXJhY3RlcmlzdGljYXNfZXNmb3Jjb19hYnVuZGFuY2lhX2RldGVjY2FvKHJlc3VsdGFkb19zZWxlY2FvX21vZGVsb3MgPSBmbHV4bzMuM19zZWxlY2FvX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUpCgpmbHV4bzMuM19jYXJhY3RlcmlzdGljYXNfZXNmb3Jjb19hYnVuZGFuY2lhX2RldGVjY2FvCmBgYAoKIyMjIyMjIENhcmFjdGVyw61zdGljYXMgZGUgZGVuc2lkYWRlCgpQcmltZWlyYSBiaW5hZ2VtCgpgYGB7cn0KIyB0b3RhbCwgZGVuc2lkYWRlIGVzdGltYWRhLCBlcnJvIHBhZHLDo28gZGEgZGVuc2lkYWRlIGRlc3RpbWFkYSwgY29lZmljaWVudGUgZGUgdmFyaWHDp8OjbyBkYSBkZW5zaWRhZGUgZGVzdGltYWRhLCBpbnRlcnZhbG8gZGUgY29uZmlhbsOnYSBpbmZlcmlvciBlIHN1cGVyaW9yIGRvIGNvZWZpY2llbnRlIGRlIHZhcmlhw6fDo28sIGdydWFzIGRlIGxpYmVyZGFkZQpmbHV4bzMuMV9jYXJhY3RlcmlzdGljYXNfZGVuc2lkYWRlIDwtIGZsdXhvMy4xX2xpc3RhX21vZGVsb3NfYWp1c3RhZG9zX3Rlcm1vcyB8PiAKICBnZXJhcl9jYXJhY3RlcmlzdGljYXNfZGVuc2lkYWRlKHJlc3VsdGFkb19zZWxlY2FvX21vZGVsb3MgPSBmbHV4bzMuMV9zZWxlY2FvX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUpCgpmbHV4bzMuMV9jYXJhY3RlcmlzdGljYXNfZGVuc2lkYWRlCmBgYAoKU2VndW5kYSBiaW5hZ2VtCgpgYGB7cn0KIyB0b3RhbCwgZGVuc2lkYWRlIGVzdGltYWRhLCBlcnJvIHBhZHLDo28gZGEgZGVuc2lkYWRlIGRlc3RpbWFkYSwgY29lZmljaWVudGUgZGUgdmFyaWHDp8OjbyBkYSBkZW5zaWRhZGUgZGVzdGltYWRhLCBpbnRlcnZhbG8gZGUgY29uZmlhbsOnYSBpbmZlcmlvciBlIHN1cGVyaW9yIGRvIGNvZWZpY2llbnRlIGRlIHZhcmlhw6fDo28sIGdydWFzIGRlIGxpYmVyZGFkZQpmbHV4bzMuMl9jYXJhY3RlcmlzdGljYXNfZGVuc2lkYWRlIDwtIGZsdXhvMy4yX2xpc3RhX21vZGVsb3NfYWp1c3RhZG9zX3Rlcm1vcyB8PiAKICBnZXJhcl9jYXJhY3RlcmlzdGljYXNfZGVuc2lkYWRlKHJlc3VsdGFkb19zZWxlY2FvX21vZGVsb3MgPSBmbHV4bzMuMl9zZWxlY2FvX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUpCgpmbHV4bzMuMl9jYXJhY3RlcmlzdGljYXNfZGVuc2lkYWRlCmBgYAoKVGVyY2VpcmEgYmluYWdlbQoKYGBge3J9CiMgdG90YWwsIGRlbnNpZGFkZSBlc3RpbWFkYSwgZXJybyBwYWRyw6NvIGRhIGRlbnNpZGFkZSBkZXN0aW1hZGEsIGNvZWZpY2llbnRlIGRlIHZhcmlhw6fDo28gZGEgZGVuc2lkYWRlIGRlc3RpbWFkYSwgaW50ZXJ2YWxvIGRlIGNvbmZpYW7Dp2EgaW5mZXJpb3IgZSBzdXBlcmlvciBkbyBjb2VmaWNpZW50ZSBkZSB2YXJpYcOnw6NvLCBncnVhcyBkZSBsaWJlcmRhZGUKZmx1eG8zLjNfY2FyYWN0ZXJpc3RpY2FzX2RlbnNpZGFkZSA8LSBmbHV4bzMuM19saXN0YV9tb2RlbG9zX2FqdXN0YWRvc190ZXJtb3MgfD4gCiAgZ2VyYXJfY2FyYWN0ZXJpc3RpY2FzX2RlbnNpZGFkZShyZXN1bHRhZG9fc2VsZWNhb19tb2RlbG9zID0gZmx1eG8zLjNfc2VsZWNhb19mdW5jYW9fZGV0ZWNjYW9fdGVybW9fYWp1c3RlKQoKZmx1eG8zLjNfY2FyYWN0ZXJpc3RpY2FzX2RlbnNpZGFkZQpgYGAKCiMjIyBBbW9zdHJhZ2VtIHBvciBEaXN0w6JuY2lhIGNvbSBNw7psdGlwbGFzIENvdmFyacOhdmVpcwoKQXF1aSwgdmFtb3MgdXNhciBhIGFib3JkYWdlbSBkbyBGbHV4byAyLCBjb20gYW1vc3RyYWdlbnMgcmVkdXppZGFzLCBwYXJhIG8gYWp1c3RlIGRlIGNvdmFyacOhdmVpcy4gVmFtb3MgdXNhciBvIHRhbWFuaG8gZG8gZ3J1cG8gY29tbyBjb3ZhcmnDoXZlbC4KCiMjIyMjIEFqdXN0YW5kbyBkaWZlcmVudGVzIG1vZGVsb3MgY29tIGNvdmFyacOhdmVpcwoKUGFyYSBvIHVzbyBkZSBjb3ZlcmnDoXZlaXMsIHBvZGVtb3MgdXNhciBzb21lbnRlIGFzIGRpc3RyaWJ1acOnw7VlcyBoYWxmLW5vcm1hbCBvdSBoYXphcmQtcmF0ZSwgcG9pcyBhbWJhcyBwb3NzdWVtIG8gcGFyw6JtZXRybyBlc2NhbGFyIHBlbG8gcXVhbCBvIHZldG9yIGRhcyBjb3ZhcmnDoXZlaXMgc2Vyw6EgbXVsdGlwbGljYWRvLiBOw6NvIMOpIHJlY29tZW5kw6F2ZWwgbyB1c28gZGUgdGVybW9zIGRlIGFqdXN0ZSBjb20gbyB1c28gZGUgY292YXJpw6F2ZWlzIHBlbGEgZ3JhbmRlIGNoYW5jZSBkZSBwZXJkYSBkZSBtb25vdG9uaWNpZGFkZSBuYXMgY3VydmFzIGRhcyBmdW7Dp8O1ZXMgZGUgZGV0ZWPDp8Ojby4gQXNzaW0sIHZhbW9zIHRyYWJhbGhhciBjb20gYXMgc2VndWludGVzIGNvbWJpbmHDp8O1ZXMgZGUgbW9kZWxvcwoKIyMjIyMjIEhhbGYtbm9ybWFsIHNlbSB0ZXJtb3MgZGUgYWp1c3RlIChITikKCmBgYHtyfQojIGFqdXN0YW5kbyBhIGZ1bsOnw6NvIGRlIGRldGVjw6fDo28gaGFsZi1ub3JtYWwgcGFyYSB1bSB0cnVuY2FtZW50byBkZSAxMCUgZG9zIGRhZG9zCmN1dGlhX2Nvdl9obiA8LSBjdXRpYV90YXBfYXJhcF9xdWFzZV9zZW1fcmVwZXRpY2FvIHw+IAogIGFqdXN0ZV9tb2RlbG9zX2Rpc3RhbmNlX2huKGxpc3RhX3Rlcm1vc19hanVzdGUgPSBsaXN0KGBTZW0gdGVybW9gPSBOVUxMKSx0cnVuY2FtZW50byA9ICIxMCUiKQpgYGAKCmxpc3RhX3Rlcm1vc19hanVzdGUgPSBsaXN0KGBTZW0gdGVybW9gKSA9IE5VTEwpLAoKIyMjIyMjIEhOICsgVGFtYW5obyBkbyBncnVwbyAoSE4gKyBTKQoKYGBge3J9CiMgYWp1c3RhbmRvIGEgZnVuw6fDo28gZGUgZGV0ZWPDp8OjbyBoYWxmLW5vcm1hbCBwYXJhIHVtIHRydW5jYW1lbnRvIGRlIDEwJSBkb3MgZGFkb3MKY3V0aWFfY292X2huX3MgPC0gY3V0aWFfdGFwX2FyYXBfcXVhc2Vfc2VtX3JlcGV0aWNhbyB8PiAKICBhanVzdGVfbW9kZWxvc19kaXN0YW5jZV9obihsaXN0YV90ZXJtb3NfYWp1c3RlID0gbGlzdChgU2VtIHRlcm1vYD0gTlVMTCksdHJ1bmNhbWVudG8gPSAiMTAlIiwgZm9ybXVsYSA9IH5zaXplKQpgYGAKCiMjIyMjIyBIYXphcmQtcmF0ZSBzZW0gdGVybW9zIGRlIGFqdXN0ZSAoSFopCgpgYGB7cn0KIyBhanVzdGFuZG8gYSBmdW7Dp8OjbyBkZSBkZXRlY8Onw6NvIGhhbGYtbm9ybWFsIHBhcmEgdW0gdHJ1bmNhbWVudG8gZGUgMTAlIGRvcyBkYWRvcwpjdXRpYV9jb3ZfaHIgPC0gY3V0aWFfdGFwX2FyYXBfcXVhc2Vfc2VtX3JlcGV0aWNhbyB8PiAKICBhanVzdGVfbW9kZWxvc19kaXN0YW5jZV9ocihsaXN0YV90ZXJtb3NfYWp1c3RlID0gbGlzdChgU2VtIHRlcm1vYD0gTlVMTCksdHJ1bmNhbWVudG8gPSAiMTAlIikKYGBgCgojIyMjIyMgSFogKyBUYW1hbmhvIGRvIGdydXBvIChIWiArIFMpCgpgYGB7cn0KIyBhanVzdGFuZG8gYSBmdW7Dp8OjbyBkZSBkZXRlY8Onw6NvIGhhbGYtbm9ybWFsIHBhcmEgdW0gdHJ1bmNhbWVudG8gZGUgMTAlIGRvcyBkYWRvcwpjdXRpYV9jb3ZfaHJfcyA8LSBjdXRpYV90YXBfYXJhcF9xdWFzZV9zZW1fcmVwZXRpY2FvIHw+IAogIGFqdXN0ZV9tb2RlbG9zX2Rpc3RhbmNlX2hyKGxpc3RhX3Rlcm1vc19hanVzdGUgPSBsaXN0KGBTZW0gdGVybW9gPSBOVUxMKSx0cnVuY2FtZW50byA9ICIxMCUiLCBmb3JtdWxhID0gfnNpemUpCmBgYAoKIyMjIyMgQ29tcGFyYW5kbyBvcyBtb2RlbG9zCgojIyMjIyMgVGFiZWxhIGNvbSBvIHJlc3VtbyBjb21wYXJhdGl2byBkb3MgbW9kZWxvcwoKQWluZGEgZXN0YW1vcyBhanVzdGFuZG8gYSBmdW7Dp8OjbyBwYXJhIHBvZGVyIGdlcmFyIGEgdGFiZWxhIGNvbSBvIHJlc3VtbyBkb3MgcmVzdWx0YWRvcy4gQSBmdW7Dp8OjbyBjcmlhZGEgcGFyYSBnZXJhciB0YWJlbGEgYWluZGEgbsOjbyBjb21wb3J0YSBvcyBkYWRvcyBkZSBtb2RlbG9zIGNvbSBjb3ZhcmnDoXZlaXMuCgpgYGB7ciwgcmVzdWx0cz0naGlkZSd9CmNvdl9saXN0YV9tb2RlbG9zX2FqdXN0YWRvcyA8LSBsaXN0KAogIGBoYWxmLW5vcm1hbGAgPSBjdXRpYV9jb3ZfaG4sIAogIGBoYXphcmQtcmF0ZWAgPSBjdXRpYV9jb3ZfaHIKKQoKY292X3NlbGVjYW9fZnVuY2FvX2RldGVjY2FvX3Rlcm1vX2FqdXN0ZSA8LSBzZWxlY2lvbmFyX2Z1bmNhb19kZXRlY2Nhb190ZXJtb19hanVzdGUoY292X2xpc3RhX21vZGVsb3NfYWp1c3RhZG9zKQpgYGAKCiMjIyMjIyBHcsOhZmljb3MgZGUgYWp1c3RlIGRhcyBmdW7Dp8O1ZXMgZGUgZGV0ZcOnw6NvIMOgcyBwcm9iYWJpbGlkYWRlcyBkZSBkZXRlw6fDo28KCkFpbmRhIGVzdGFtb3MgYWp1c3RhbmRvIGEgZnVuw6fDo28gcGFyYSBwb2RlciBnZXJhciBvcyBncsOhZmljb3MgZG9zIG1vZGVsb3MgY29tIGNvdmFyacOhdmVpcy4gQSBmdW7Dp8OjbyBjcmlhZGEgcGFyYSBvcyBncsOhZmljb3MgYWluZGEgbsOjbyBjb21wb3J0YSBvcyBkYWRvcyBkZSBtb2RlbG9zIGNvbSBjb3ZhcmnDoXZlaXMuCgpgYGB7cn0KY292X21vZGVsb3Nfc2VsZWNpb25hZG9zIDwtIGxpc3QoCiAgY3V0aWFfY292X2huJGBTZW0gdGVybW9gLAogIGN1dGlhX2Nvdl9ociRgU2VtIHRlcm1vYAopCgpwbG90YXJfZnVuY2FvX2RldGVjY2FvX21vZGVsb3Nfc2VsZWNpb25hZG9zKGNvdl9tb2RlbG9zX3NlbGVjaW9uYWRvcykKYGBgCgojIyMjIyMgVGVzdGUgZGUgYm9uZGFkZSBkZSBhanVzdGUgZG9zIG1vZGVsb3MgZSBRLVEgcGxvdHMKCkFpbmRhIGVzdGFtb3MgYWp1c3RhbmRvIGEgZnVuw6fDo28gcGFyYSBwb2RlciBnZXJhciBhIHRhYmVsYSBjb20gb3MgcmVzdWx0YWRvcyBkbyBDcmFtw6lyLXZvbiBNaXNlcyBlIG9zIGdyw6FmaWNvcyBkb3MgbW9kZWxvcyBjb20gY292YXJpw6F2ZWlzLiBBIGZ1bsOnw6NvIGNyaWFkYSBwYXJhIGdlcmFyIHRhYmVsYSBlIG9zIFEtUSBwbG90cyBhaW5kYSBuw6NvIGNvbXBvcnRhIG9zIGRhZG9zIGRlIG1vZGVsb3MgY29tIGNvdmFyacOhdmVpcy4KCmBgYHtyfQpib25kYWRlX2FqdXN0ZV9jb3YgPC0gdGVzdGFyX2JvbmRhZGVfYWp1c3RlKGNvdl9tb2RlbG9zX3NlbGVjaW9uYWRvcywgcGxvdCA9IFRSVUUpCmJvbmRhZGVfYWp1c3RlX2NvdgpgYGAKCiMjIyMjIEF2YWxpYW5kbyBhcyBlc3RpbWF0aXZhcyBkZSBBYnVuZMOibmNpYSBlIERlbnNpZGFkZQoKUGFyYSBvIHVzbyBkZSBjb3ZhcmnDoXZlaXMsIGFzIGVzdGltYXRpdmFzIGRlIGFidW5kw6JuY2lhL2RlbnNpZGFkZSBkZXZlbSBzZXIgZmVpdGFzIGF0cmF2w6lzIGRvIGJvb3RzdHJhcCAoZnVuw6fDo28gYGJvb3RkaHRgIGRvIERpc3RhbmNlKS4gQWluZGEgZXN0YW1vcyBpbXBsZW1lbnRhbmRvIG8gYm9vdHN0cmFwIGVtIG5vc3NvIGZsdXhvIGRlIGVzdGltYXRpdmFzIGRlIHRheGEgZGUgZW5jb250cm8sIGFidW5kw6JuY2lhIGUgZGVuc2lkYWRlLgo=